Skip to content

Commit

Permalink
feat: add config related functions #10
Browse files Browse the repository at this point in the history
  • Loading branch information
inazarov committed Feb 3, 2022
1 parent 6ba38bc commit 1e90ad9
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 19 deletions.
1 change: 1 addition & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './type/contract-map'
export * from './type/enum-interaction-type'
export * from './type/i-deploy-props'
export * from './type/i-fcl-wallet'
export * from './type/i-flow-account'
export * from './type/i-interaction'
Expand Down
10 changes: 10 additions & 0 deletions lib/type/i-deploy-props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Argument } from '@onflow/types'
import { IFlowAccount } from './i-flow-account'

export interface IDeployProps {
auth: IFlowAccount
name: string
to?: string
args?: Argument[]
update?: boolean
}
139 changes: 139 additions & 0 deletions lib/util/config.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { AnyJson } from '@samatech/onflow-fcl-esm'
import { ContractMap } from '../type/contract-map'
import {
getAddressMap,
setAddressMap,
getContractAddress,
setContractAddress,
configGet,
flowConfigGet,
} from './config'

console.warn = jest.fn()

const flowJson: AnyJson = {
emulators: { default: { port: 3569, serviceAccount: 'emulator-account' } },
accounts: {
'emulator-account': {
address: '01cf0e2f2f715450',
key: 'key',
pubKey: 'pubKey',
},
},
contracts: {
NonFungibleToken: {
source: './NonFungibleToken.cdc',
aliases: {
emulator: '0xf8d6e0586b0a20c7',
testnet: '0x631e88ae7f1d7c20',
},
},
},
networks: {
emulator: '127.0.0.1:3569',
testnet: 'access.devnet.nodes.onflow.org:9000',
},
}

const addressMap: ContractMap = {
FlowToken: '0x0ae53cb6e3f42a79',
FungibleToken: '0xee82856bf20e2aa6',
FlowFees: '0xe5a8b7f23e8b548f',
FlowStorageFees: '0xf8d6e0586b0a20c7',
}

const newContractName = 'SomeContract'
const newContractAddress = '0xe2c5a5f23e8b743c'

const getAddressMapWithNewContract = (): ContractMap => {
return {
...getAddressMap(),
...{ [newContractName]: newContractAddress },
}
}

describe('config', () => {
describe('getAddressMap', () => {
beforeEach(() => {
setAddressMap({})
})

it('returns the address map', () => {
expect(getAddressMap()).toEqual(addressMap)
})

it('returns the address map with the new contract', () => {
setContractAddress(newContractName, newContractAddress)
expect(getAddressMap()).toEqual(getAddressMapWithNewContract())
})
})

describe('setAddressMap', () => {
beforeEach(() => {
setAddressMap({})
})

it('set address map without affecting defaults', () => {
setAddressMap({ [newContractName]: newContractAddress })
expect(getAddressMap()).toEqual(getAddressMapWithNewContract())
})
})

describe('getContractAddress', () => {
beforeEach(() => {
setAddressMap({})
})

it('returns a specific contract address', () => {
expect(getContractAddress('FlowToken')).toEqual(addressMap.FlowToken)
})

it('returns undefined if contract name does not exist', () => {
expect(getContractAddress('BogusContractName')).toEqual(undefined)
})
})

describe('setContractAddress', () => {
beforeEach(() => {
setAddressMap({})
})

it('adds a new contract name/address pair to the contracts map', () => {
setContractAddress(newContractName, newContractAddress)
expect(getContractAddress(newContractName)).toEqual(newContractAddress)
})
})

describe('flowConfigGet', () => {
it('returns configuration value for the given path', () => {
const path = 'accounts/emulator-account/address'
expect(flowConfigGet(flowJson, path)).toBe('01cf0e2f2f715450')
})

it('returns undefined if found configuration value is not a string', () => {
const path = 'accounts/emulator-account'
expect(flowConfigGet(flowJson, path)).toBe(undefined)
expect(console.warn).toHaveBeenCalledWith(
'Config "accounts/emulator-account" not found, fallback=""',
)
})

it('returns undefined if path does not exist', () => {
expect(flowConfigGet(flowJson, 'bogus/path')).toBe(undefined)
expect(console.warn).toHaveBeenCalledWith(
'Config "bogus/path" not found, fallback=""',
)
})
})

describe('configGet', () => {
it('returns the configuration value for the given path', () => {
const path = 'contracts/NonFungibleToken/source'
expect(configGet(flowJson, path, 'fallback')).toBe('./NonFungibleToken.cdc')
})

it('returns a fallback value if given path not found', () => {
expect(configGet(flowJson, 'bogus/path', 'fallback')).toBe('fallback')
})
})
})
66 changes: 61 additions & 5 deletions lib/util/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AnyJson, IJsonObject } from '@samatech/onflow-fcl-esm'
import { ContractMap } from '../type/contract-map'

/**
Expand All @@ -11,19 +12,74 @@ export const defaultsByName: ContractMap = {
FlowStorageFees: '0xf8d6e0586b0a20c7',
}

const contractsMap: ContractMap = {}

export const setContractAddress = (name: string, address: string): void => {
contractsMap[name] = address
}
let contractsMap: ContractMap = {}

/**
* Returns the full contract address map object.
* @returns {ContractMap} the full contact map that includes default and custom addresses
*/
export const getAddressMap = (): ContractMap => {
return {
...defaultsByName,
...contractsMap,
}
}

/**
* Sets the custom contracts map without affecting the defaults
* @param {ContractMap} contracts - the custom contracts map
*/
export const setAddressMap = (contracts: ContractMap): void => {
contractsMap = contracts
}

/**
* Returns a specific contract address based on the key name.
* @param {string} key - the contract name
* @returns {string|undefined} either a contract address if found or undefined
*/
export const getContractAddress = (key: string): string | undefined => {
return getAddressMap()[key]
}

/**
* Adds a new contract name/address pair to the contracts map
* @param {string} name - new contract name
* @param {string} address - new contract address
*/
export const setContractAddress = (name: string, address: string): void => {
contractsMap[name] = address
}

/**
* Get value from provided scope and path.
* @param scope - scope value.
* @param {string} path - path of value in flow.json
* @returns {string|undefined} either a config value if found or undefined
*/
export const flowConfigGet = (flowConfig: AnyJson, path: string): string | undefined => {
return configGet(flowConfig, path, '') || undefined
}

/**
* Get value from provided scope and path.
* @param scope - scope value.
* @param {string} path - path of value in flow.json
* @param fallback - fallback value.
* @returns {string|undefined} either a config value if found or a fallback value
*/
export const configGet = (scope: AnyJson, path: string, fallback: string): string => {
const pathArr = path.split('/')
let obj = scope
for (const pathKey of pathArr) {
if (typeof obj !== 'object') {
break
}
obj = (obj as IJsonObject)[pathKey]
}
if (!obj || typeof obj !== 'string') {
console.warn(`Config "${path}" not found, fallback="${fallback}"`)
return fallback
}
return obj
}
6 changes: 6 additions & 0 deletions lib/util/find-event.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { CadenceEvent } from '@samatech/onflow-fcl-esm'

/**
* Returns an event for the given type
* @param {CadenceEvent[]} events - events where to search
* @param {string} eventType - the type of the event to search for
* @returns {CadenceEvent|undefined} returns the event if found; otherwise - undefined
*/
export const findEvent = (
events: CadenceEvent[],
eventType: string,
Expand Down
9 changes: 8 additions & 1 deletion lib/util/get-event-id.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { sansPrefix } from '@samatech/onflow-fcl-esm'

// Get event id
/**
* Returns a full event id based on provided parameters
* @param {string} contractAddress - the contract address
* @param {string} contractName - the contract name
* @param {string} eventName - the event name
* @param {string} [eventPrefix='A'] - an event prefix
* @returns {string} returns the full event id
*/
export const getEventId = (
contractAddress: string,
contractName: string,
Expand Down
12 changes: 2 additions & 10 deletions lib/util/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { withPrefix } from './misc'

import { InteractionType } from '../type/enum-interaction-type'
import { ContractMap } from '../type/contract-map'
import { IFlowAccount } from '../type/i-flow-account'
import { IDeployProps } from '../type/i-deploy-props'
import { IInteraction } from '../type/i-interaction'
import { ITransactProps } from '../type/i-transact-props'
import { IInteractionProps } from '../type/i-interaction-props'
Expand Down Expand Up @@ -191,20 +191,12 @@ export const execute = async (name: string, args?: fcl.Argument[]): Promise<any>
return executeScript({ args, code })
}

export interface DeployProps {
auth: IFlowAccount
name: string
to?: string
args?: fcl.Argument[]
update?: boolean
}

/**
* Deploys contract as Cadence code to specified account
* Returns transaction result.
* @param props - Deploy properties
*/
export const deployContract = async (props: DeployProps) => {
export const deployContract = async (props: IDeployProps) => {
const { auth, name, args, update, to } = props

const resolvedTo = withPrefix(to ?? auth.address)
Expand Down
12 changes: 11 additions & 1 deletion lib/util/misc.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { withPrefix } from './misc'
import { toUFix64, withPrefix } from './misc'

describe('util-flow', () => {
describe('toUFix64', () => {
it('returns a string representation of a UFix64 integer (8 decimal places)', () => {
expect(toUFix64(12)).toBe(`12.00000000`)
})

it('returns a string representation of a UFix64 float (8 decimal places)', () => {
expect(toUFix64(12.12345678)).toBe(`12.12345678`)
})
})

describe('withPrefix', () => {
it('returns address with prefix if no prefix is found', () => {
const address = '0ae53cb6e3f42a79'
Expand Down
13 changes: 12 additions & 1 deletion lib/util/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@ import { sansPrefix } from '@samatech/onflow-fcl-esm'

const UFIX64_PRECISION = 8

// UFix64 values shall be always passed as strings
/**
* Returns a string representation of the 64-bit unsigned fixed number
* It's always represented with 8 decimal places
* @param {number} value - a number to be converted to UFix64 string format
* @returns {string} a string in the UFix64 format
*/
export const toUFix64 = (value: number): string => value.toFixed(UFIX64_PRECISION)

/**
* Adds a hexadecimal prefix if one does not exist
* @param {string} address - an address to add a hexadecimal prefix to
* @returns {string} either an address with hexadecimal prefix or undefined value
* if the passed in address is undefined
*/
export const withPrefix = (address?: string): string | undefined => {
if (!address) return address
return `0x${sansPrefix(address)}`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@
"ts-node": "^10.4.0",
"typescript": "^4.5.4"
}
}
}

0 comments on commit 1e90ad9

Please sign in to comment.