@alephium/web3-test
Version:
Utility functions for Alephium test
157 lines (137 loc) • 5.07 kB
text/typescript
/*
Copyright 2018 - 2022 The Alephium Authors
This file is part of the alephium project.
The library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the library. If not, see <http://www.gnu.org/licenses/>.
*/
import 'cross-fetch/polyfill'
import {
addressFromContractId,
isBase58,
NodeProvider,
ONE_ALPH,
ALPH_TOKEN_ID,
DUST_AMOUNT,
Address,
TOTAL_NUMBER_OF_GROUPS,
binToHex,
TraceableError
} from '@alephium/web3'
import { NodeWallet, PrivateKeyWallet } from '@alephium/web3-wallet'
import { randomBytes } from 'crypto'
import {
testAddress,
testMnemonic,
testPassword,
testPrivateKeyWallet,
testWalletName,
tryGetDevnetNodeProvider
} from './const'
async function prepareWallet(testNodeProvider: NodeProvider) {
const wallets = await testNodeProvider.wallets.getWallets()
if (wallets.find((wallet) => wallet.walletName === testWalletName)) {
await unlockWallet(testNodeProvider)
} else {
await createWallet(testNodeProvider)
}
}
async function changeActiveAddress(testNodeProvider: NodeProvider) {
await testNodeProvider.wallets.postWalletsWalletNameChangeActiveAddress(testWalletName, {
address: testAddress
})
}
async function createWallet(testNodeProvider: NodeProvider) {
await testNodeProvider.wallets.putWallets({
password: testPassword,
mnemonic: testMnemonic,
walletName: testWalletName,
isMiner: true
})
await changeActiveAddress(testNodeProvider)
}
async function unlockWallet(testNodeProvider: NodeProvider) {
await testNodeProvider.wallets.postWalletsWalletNameUnlock(testWalletName, { password: testPassword })
await changeActiveAddress(testNodeProvider)
}
export async function testNodeWallet(baseUrl = 'http://127.0.0.1:22973'): Promise<NodeWallet> {
const nodeProvider = new NodeProvider(baseUrl, undefined, (...params: Parameters<typeof fetch>) => fetch(...params))
await prepareWallet(nodeProvider)
const wallet = new NodeWallet(testWalletName, nodeProvider)
await wallet.unlock(testPassword)
return wallet
}
function checkGroup(group: number) {
if (group < 0 || group >= TOTAL_NUMBER_OF_GROUPS) {
throw new Error('Invalid group index')
}
}
export async function getSigner(alphAmount = ONE_ALPH * 100n, group = 0): Promise<PrivateKeyWallet> {
checkGroup(group)
try {
const nodeProvider = await tryGetDevnetNodeProvider()
const balances = await nodeProvider.addresses.getAddressesAddressBalance(testAddress)
const availableBalance = BigInt(balances.balance) - BigInt(balances.lockedBalance)
if (availableBalance < alphAmount) {
throw new Error('Not enough balance, please restart the devnet')
}
const wallet = PrivateKeyWallet.Random(group)
if (alphAmount > 0n) {
const destinations = [{ address: wallet.address, attoAlphAmount: alphAmount }]
await testPrivateKeyWallet.signAndSubmitTransferTx({ signerAddress: testAddress, destinations })
}
return wallet
} catch (error) {
throw new TraceableError(`Failed to get signer, please restart the devnet`, error)
}
}
export async function getSigners(
num: number,
alphAmountPerSigner = ONE_ALPH * 100n,
group = 0
): Promise<PrivateKeyWallet[]> {
checkGroup(group)
try {
const wallets: PrivateKeyWallet[] = []
for (let index = 0; index < num; index++) {
const wallet = await getSigner(alphAmountPerSigner, group)
wallets.push(wallet)
}
return wallets
} catch (error) {
throw new TraceableError('Failed to get signers, please restart the devnet', error)
}
}
export async function transfer(from: PrivateKeyWallet, to: Address, tokenId: string, amount: bigint) {
const destination = {
address: to,
attoAlphAmount: tokenId === ALPH_TOKEN_ID ? amount : DUST_AMOUNT,
tokens: tokenId === ALPH_TOKEN_ID ? [] : [{ id: tokenId, amount }]
}
return await from.signAndSubmitTransferTx({ signerAddress: from.address, destinations: [destination] })
}
export async function expectAssertionError(
p: Promise<unknown>,
address: string,
errorCode: number | bigint
): Promise<void> {
expect(isBase58(address)).toEqual(true)
await expect(p).rejects.toThrowError(
new RegExp(`Assertion Failed in Contract @ ${address}, Error Code: ${errorCode}`, 'mg')
)
}
export function randomContractId(groupIndex = 0): string {
checkGroup(groupIndex)
const bytes = new Uint8Array([...randomBytes(31), groupIndex])
return binToHex(bytes)
}
export function randomContractAddress(groupIndex = 0): string {
return addressFromContractId(randomContractId(groupIndex))
}