-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* wip: created pure functions for balance * WIP: add testing infra for unit tests * wip: got tests to pass, adding new ones * added test for all bad addresses * updated user flows to use the new pure function to grab balance * updated changelog * Update src/common/initializeEntropy.ts Co-authored-by: Frankie <frankie.diamond@gmail.com> * Update src/common/initializeEntropy.ts Co-authored-by: Frankie <frankie.diamond@gmail.com> * adding actions * updated rc for sdk package * removing docker hub from actions --------- Co-authored-by: Nayyir Jutha <nayyir@entropy.xyz> Co-authored-by: Nayyir Jutha <nayyir.jutha@gmail.com> Co-authored-by: Frankie <frankie.diamond@gmail.com>
- Loading branch information
1 parent
93c3d05
commit 47ae2ca
Showing
13 changed files
with
289 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--- | ||
name: Build, lint, test | ||
run-name: Test JS CLI (started by @${{ github.triggering_actor }}) | ||
|
||
on: | ||
pull_request: | ||
types: | ||
- opened | ||
- synchronize | ||
- reopened | ||
|
||
jobs: | ||
build_test_lint: | ||
name: Build, test, and lint | ||
permissions: | ||
contents: read | ||
runs-on: ubuntu-22.04 | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: 20.10.0 | ||
- name: Install | ||
run: yarn --network-timeout 180000 | ||
- name: Typecheck | ||
run: yarn run test:types | ||
- name: Build | ||
run: yarn run build | ||
- name: Add TSS server host mappings | ||
run: | | ||
echo "127.0.0.1 alice-tss-server bob-tss-server" | sudo tee -a /etc/hosts | ||
- name: Test | ||
run: yarn run test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import Entropy from "@entropyxyz/sdk"; | ||
import { BalanceInfo } from "./types"; | ||
|
||
const hexToBigInt = (hexString: string) => BigInt(hexString) | ||
|
||
export async function getBalance (entropy: Entropy, address: string): Promise<number> { | ||
try { | ||
const accountInfo = (await entropy.substrate.query.system.account(address)) as any | ||
|
||
return parseInt(hexToBigInt(accountInfo.data.free).toString()) | ||
} catch (error) { | ||
// console.error(`There was an error getting balance for [acct = ${address}]`, error); | ||
throw new Error(error.message) | ||
} | ||
} | ||
|
||
export async function getBalances (entropy: Entropy, addresses: string[]): Promise<BalanceInfo> { | ||
const balanceInfo: BalanceInfo = {} | ||
try { | ||
await Promise.all(addresses.map(async address => { | ||
try { | ||
const balance = await getBalance(entropy, address) | ||
|
||
balanceInfo[address] = { balance } | ||
} catch (error) { | ||
// console.error(`Error retrieving balance for ${address}`, error); | ||
balanceInfo[address] = { error: error.message } | ||
} | ||
})) | ||
|
||
return balanceInfo | ||
} catch (error) { | ||
// console.error(`There was an error getting balances for [${addresses}]`, error); | ||
throw new Error(error.message) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,16 @@ | ||
import { initializeEntropy } from "../../common/initializeEntropy" | ||
import { print, debug, getSelectedAccount } from "../../common/utils" | ||
import { getBalance } from "./balance"; | ||
|
||
const hexToBigInt = (hexString: string) => BigInt(hexString) | ||
|
||
|
||
// TO-DO setup flow method to provide options to allow users to select account, | ||
// use external address, or get balances for all accounts in config | ||
export async function checkBalance ({ accounts, selectedAccount: selectedAccountAddress }, options) { | ||
const { endpoint } = options | ||
debug('endpoint', endpoint); | ||
|
||
const selectedAccount = getSelectedAccount(accounts, selectedAccountAddress) | ||
const entropy = await initializeEntropy({ keyMaterial: selectedAccount.data, endpoint }); | ||
const accountAddress = selectedAccountAddress | ||
// @ts-ignore | ||
const accountInfo = (await entropy.substrate.query.system.account(accountAddress)) as any | ||
const freeBalance = hexToBigInt(accountInfo.data.free) | ||
const freeBalance = await getBalance(entropy, accountAddress) | ||
print(`Address ${accountAddress} has a balance of: ${freeBalance.toLocaleString('en-US')} BITS`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export type BalanceInfoWithError = { | ||
balance?: number | ||
error?: Error | ||
} | ||
|
||
export interface BalanceInfo { | ||
[address: string]: BalanceInfoWithError | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import test from 'tape' | ||
import Entropy, { wasmGlobalsReady } from '@entropyxyz/sdk' | ||
// WIP: I'm seeing problems importing this? | ||
import Keyring from '@entropyxyz/sdk/dist/keys/index' | ||
import { | ||
makeSeed, | ||
promiseRunner, | ||
sleep, | ||
spinNetworkUp, | ||
spinNetworkDown | ||
} from './testing-utils' | ||
|
||
import { getBalance, getBalances } from '../src/flows/balance/balance' | ||
import { initializeEntropy } from 'src/common/initializeEntropy' | ||
|
||
const networkType = 'two-nodes' | ||
|
||
// TODO: export charlieStashSeed | ||
const richAddress = '5Ck5SLSHYac6WFt5UZRSsdJjwmpSZq85fd5TRNAdZQVzEAPT' | ||
|
||
test('getBalance + getBalances', async (t) => { | ||
/* Setup */ | ||
const run = promiseRunner(t) | ||
await run('wasm', wasmGlobalsReady()) | ||
await run('network up', spinNetworkUp(networkType)) | ||
// this gets called after all tests are run | ||
t.teardown(async () => { | ||
await entropy.close() | ||
await spinNetworkDown(networkType).catch((error) => | ||
console.error('Error while spinning network down', error.message) | ||
) | ||
}) | ||
await sleep(process.env.GITHUB_WORKSPACE ? 30_000 : 5_000) | ||
|
||
const newSeed = makeSeed() | ||
const entropy = await initializeEntropy({ keyMaterial: { seed: newSeed, debug: true }, endpoint: 'ws://127.0.0.1:9944', }) | ||
const newAddress = entropy.keyring.accounts.registration.address | ||
|
||
await run('entropy ready', entropy.ready) | ||
|
||
/* getBalance */ | ||
const newAddressBalance = await run( | ||
'getBalance (newSeed)', | ||
getBalance(entropy, newAddress) | ||
) | ||
|
||
t.equal(newAddressBalance, 0, 'newSeed balance = 0') | ||
|
||
const richAddressBalance = await run( | ||
'getBalance (richAddress)', | ||
getBalance(entropy, richAddress) | ||
) | ||
|
||
t.true(richAddressBalance > BigInt(10e10), 'richAddress balance >>> 0') | ||
|
||
/* getBalances */ | ||
|
||
const balances = await run( | ||
'getBalances', | ||
getBalances(entropy, [newAddress, richAddress]) | ||
) | ||
|
||
t.deepEqual( | ||
balances, | ||
{ | ||
[newAddress]: {balance: newAddressBalance}, | ||
[richAddress]: {balance: richAddressBalance} | ||
}, | ||
'getBalances works' | ||
) | ||
|
||
const badAddresses = ['5Cz6BfUaxxXCA3jninzxdan4JdmC1NVpgkiRPYhXbhr', '5Cz6BfUaxxXCA3jninzxdan4JdmC1NVpgkiRPYhXbhrfnD'] | ||
const balancesWithNoGoodAddress = await run( | ||
'getBalances::one good address', | ||
getBalances(entropy, badAddresses) | ||
) | ||
|
||
badAddresses.forEach(addr => { | ||
t.true(!!balancesWithNoGoodAddress[addr].error, `error field is populated for ${addr}`) | ||
}) | ||
// TODO: | ||
// - test getBalances with 1 good address, 1 bung seed | ||
|
||
t.end() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { spinNetworkUp, spinNetworkDown, } from "@entropyxyz/sdk/dev/testing-utils.mjs" | ||
// import { spinNetworkUp, spinNetworkDown, } from "@entropyxyz/sdk/testing" | ||
import * as readline from 'readline' | ||
import { randomBytes } from 'crypto' | ||
|
||
export { | ||
spinNetworkUp, | ||
spinNetworkDown, | ||
} | ||
|
||
/* Helper for wrapping promises which makes it super clear in logging if the promise | ||
* resolves or threw. | ||
* | ||
* @param {any} t - an instance to tape runner | ||
* @param {boolean} keepThrowing - toggle throwing | ||
*/ | ||
export function promiseRunner(t: any, keepThrowing = false) { | ||
// NOTE: this function swallows errors | ||
return async function run( | ||
message: string, | ||
promise: Promise<any> | ||
): Promise<any> { | ||
if (promise.constructor !== Promise) { | ||
t.pass(message) | ||
return Promise.resolve(promise) | ||
} | ||
|
||
const startTime = Date.now() | ||
return promise | ||
.then((result) => { | ||
const time = (Date.now() - startTime) / 1000 | ||
const pad = Array(40 - message.length) | ||
.fill('-') | ||
.join('') | ||
t.pass(`${message} ${pad} ${time}s`) | ||
return result | ||
}) | ||
.catch((err) => { | ||
t.error(err, message) | ||
if (keepThrowing) throw err | ||
}) | ||
} | ||
} | ||
|
||
const SLEEP_DONE = '▓' | ||
const SLEEP_TODO = '░' | ||
|
||
export function sleep(durationInMs: number) { | ||
return new Promise((resolve) => { | ||
let count = 0 | ||
|
||
readline.cursorTo(process.stdout, 2) | ||
|
||
const steps = Math.min(Math.round(durationInMs / 1000), 80) | ||
const stepLength = durationInMs / steps | ||
|
||
console.log('') // write blank link to overwrite | ||
const interval = setInterval(step, stepLength) | ||
|
||
function step() { | ||
count++ | ||
|
||
if (count >= steps) { | ||
clearInterval(interval) | ||
|
||
undoLastLine() | ||
console.log(`sleep (${durationInMs / 1000}s)`) | ||
resolve('DONE') | ||
return | ||
} | ||
|
||
undoLastLine() | ||
console.log( | ||
[ | ||
'sleep ', | ||
...Array(count).fill(SLEEP_DONE), | ||
...Array(steps - count).fill(SLEEP_TODO), | ||
'\n', | ||
].join('') | ||
) | ||
} | ||
}) | ||
} | ||
function undoLastLine() { | ||
readline.moveCursor(process.stdout, 0, -1) | ||
readline.cursorTo(process.stdout, 0) | ||
readline.clearLine(process.stdout, 0) | ||
readline.cursorTo(process.stdout, 4) // indent | ||
} | ||
|
||
export function makeSeed () { | ||
return '0x' + randomBytes(32).toString('hex') | ||
} |
Oops, something went wrong.