Skip to content

Instantly share code, notes, and snippets.

@CertainLach
Created March 3, 2023 15:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CertainLach/0fbe19dc173714595b064ff1289c99d5 to your computer and use it in GitHub Desktop.
Save CertainLach/0fbe19dc173714595b064ff1289c99d5 to your computer and use it in GitHub Desktop.
import { ApiPromise } from '@polkadot/api';
import { usingApi, privateKey, sendBalances, sleep, onlySign, signSendAndWait } from './lib';
const main = async (wsEndpoint, accountsCount = 8_000, donorSeed = '//Alice', accountPrefix = 'Account') => {
await usingApi(wsEndpoint, async (api: ApiPromise) => {
const donor = await privateKey(donorSeed);
const accounts = [];
console.time('accounts');
for(let i = accountsCount; i--;) {
accounts.push((await privateKey(`//${accountPrefix}-${i}`)));
}
console.timeEnd('accounts');
await sendBalances(api, donor, accounts, 2n * 10n ** 17n);
});
}
main(['ws://parachain-gateway-deu.cluster.local']).then(() => process.exit(0)).catch(e => {
console.error(e);
process.exit(1);
});
import { ApiPromise, Keyring, WsProvider } from '@polkadot/api';
import { cryptoIsReady, cryptoWaitReady } from '@polkadot/util-crypto';
import {SignerOptions, SubmittableExtrinsic} from '@polkadot/api/types/submittable';
import {ISubmittableResult, IKeyringPair} from '@polkadot/types/types';
import { ApiTypes } from '@polkadot/api/types';
export type TxResult = {
status: 'success' | 'fail',
reason?: string,
result?: ISubmittableResult,
}
export type Tx = {
signer: IKeyringPair,
extrinsic: SubmittableExtrinsic<'promise', ISubmittableResult>,
options?: Partial<SignerOptions> | undefined,
}
export const getCb = (unsub: () => void, resolve: (value: any) => void): (result: ISubmittableResult) => void => {
return (result) => {
const {events, status } = result;
// If the transaction wasn't included in the block for some reason:
if (status.isDropped) {
console.log('TX DROPPED');
unsub();
resolve({status: 'fail', reason: 'ExtrinsicDropped', result});
}
else if (status.isFinalized || status.isInBlock) {
const errors = events.filter(e => e.event.method === 'ExtrinsicFailed');
if (errors.length > 0) {
unsub();
resolve({status: 'fail', reason: 'ExtrinsicFailed', result});
}
unsub();
resolve({status: 'success', result});
}
else if (status.isRetracted) {
console.log('TX RECTRACTED');
}
else if (status.isInvalid) {
console.log('TX INVALID');
}
else if (status.isFinalityTimeout) {
console.log('TX FINALITY TIMEOUT');
}
else if (status.isNone) {
console.log('TX IS NONE');
}
else if (status.isUsurped) {
console.log('TX IS USURPED');
}
else if (status.isBroadcast) {}
else {
console.log('Unknown status', status, result);
}
};
}
export const signSendAndWait = (transaction: Tx): Promise<TxResult> => {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => {
try {
const {signer, extrinsic, options} = transaction;
const unsub = await extrinsic.signAndSend(signer, options ? options : {}, getCb(() => unsub(), resolve));
} catch (error) {
const reason = error instanceof Error ? error.message : `Unknown error: ${error}`;
resolve({status: 'fail', reason});
}
});
}
export const onlySign = async (transaction: Tx): Promise<SubmittableExtrinsic<ApiTypes, ISubmittableResult>> => {
return await transaction.extrinsic.signAsync(transaction.signer, transaction.options);
}
export const usingApi = async (wsEndpoint: string, func: (api: ApiPromise) => Promise<void>, options?: {[key: string]: any}) => {
const api = new ApiPromise({provider: new WsProvider(wsEndpoint), ...options});
await api.isReadyOrError;
try {
await func(api);
}
catch(e) {
console.error(e);
}
await api.disconnect();
}
export const privateKey = async (seed: string) => {
if(!cryptoIsReady()) await cryptoWaitReady();
return (new Keyring({type: 'sr25519'})).addFromUri(seed);
}
export const sleep = (time: number) => {
return new Promise((resolve: (value: unknown) => void) => {
setTimeout(() => resolve(true), time);
});
}
export const sendBalances = async (api: ApiPromise, signer: IKeyringPair, accounts: IKeyringPair[], sum = 200n * 10n ** 18n) => {
console.time('balances sign');
let signerAccount = (await api.query.system.account(signer.address)).toJSON() as any;
console.log(signerAccount);
let nonce = signerAccount.nonce;
console.log('signer', signer.address);
console.log('signer nonce', nonce);
const txs = [] as any;
for(let acc of accounts) {
txs.push({
nonce: nonce,
tx: await onlySign({
signer: signer,
extrinsic: api.tx.balances.transfer(acc.address, sum),
options: {era: 0, nonce: nonce++}
})
});
}
console.timeEnd('balances sign');
console.time('balances send')
let chunk = [];
for(let tx of txs) {
if(tx.nonce % 100 === 0) console.log('Send ', tx.nonce);
chunk.push(async () => await tx.tx.send());
if(chunk.length >= 30) {
await Promise.all(chunk.map(x => x()));
chunk = [];
}
}
if(chunk.length > 0) await Promise.all(chunk.map(x => x()));
console.timeEnd('balances send');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment