@polkadot/api#Keyring TypeScript Examples
The following examples show how to use
@polkadot/api#Keyring.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts From bodhi.js with Apache License 2.0 | 7 votes |
setup = async (urlOverwrite?: string) => {
const url = urlOverwrite || process.env.ENDPOINT_URL || DEFAULT_URL;
const seed = process.env.SEED;
const provider = new Provider({
provider: new WsProvider(url)
});
await provider.api.isReady;
console.log(`provider connected to ${url}`);
let pair: KeyringPair;
if (seed) {
const keyring = new Keyring({ type: 'sr25519' });
pair = keyring.addFromUri(seed);
} else {
const testPairs = createTestPairs();
pair = testPairs.alice;
}
const signingKey = new AccountSigningKey(provider.api.registry);
signingKey.addKeyringPair(pair);
const wallet = new Signer(provider, pair.address, signingKey);
return {
wallet,
provider,
pair
};
}
Example #2
Source File: spec.ts From polkadot-launch with MIT License | 6 votes |
// Add additional authorities to chain spec in `session.keys`
export async function addAuthority(spec: string, name: string) {
await cryptoWaitReady();
const sr_keyring = new Keyring({ type: "sr25519" });
const sr_account = sr_keyring.createFromUri(`//${nameCase(name)}`);
const sr_stash = sr_keyring.createFromUri(`//${nameCase(name)}//stash`);
const ed_keyring = new Keyring({ type: "ed25519" });
const ed_account = ed_keyring.createFromUri(`//${nameCase(name)}`);
const ec_keyring = new Keyring({ type: "ecdsa" });
const ec_account = ec_keyring.createFromUri(`//${nameCase(name)}`);
let key = [
sr_stash.address,
sr_stash.address,
{
grandpa: ed_account.address,
babe: sr_account.address,
im_online: sr_account.address,
parachain_validator: sr_account.address,
authority_discovery: sr_account.address,
para_validator: sr_account.address,
para_assignment: sr_account.address,
beefy: encodeAddress(ec_account.publicKey),
},
];
let rawdata = fs.readFileSync(spec);
let chainSpec = JSON.parse(rawdata);
let keys = getAuthorityKeys(chainSpec);
keys.push(key);
let data = JSON.stringify(chainSpec, null, 2);
fs.writeFileSync(spec, data);
console.log(` ? Added Genesis Authority ${name}`);
}
Example #3
Source File: index.ts From parachain-launch with Apache License 2.0 | 6 votes |
getAddress = (val: string) => {
try {
const addr = decodeAddress(val);
return encodeAddress(addr);
} catch {}
const keyring = new Keyring();
const pair = keyring.createFromUri(`//${_.startCase(val)}`, undefined, 'sr25519');
return pair.address;
}
Example #4
Source File: system.test.ts From interbtc-api with Apache License 2.0 | 6 votes |
describe("systemAPI", () => {
let api: ApiPromise;
let sudoAccount: KeyringPair;
let interBtcAPI: InterBtcApi;
let keyring: Keyring;
before(async () => {
api = await createSubstrateAPI(PARACHAIN_ENDPOINT);
keyring = new Keyring({ type: "sr25519" });
sudoAccount = keyring.addFromUri(SUDO_URI);
interBtcAPI = new DefaultInterBtcApi(api, "regtest", sudoAccount, ESPLORA_BASE_PATH);
});
after(async () => {
api.disconnect();
});
it("should getCurrentBlockNumber", async () => {
const currentBlockNumber = await interBtcAPI.system.getCurrentBlockNumber();
assert.isDefined(currentBlockNumber);
});
it("should getStatusCode", async () => {
const statusCode = await interBtcAPI.system.getStatusCode();
assert.isDefined(statusCode);
});
// TODO: Unskip once differences between rococo-local and standalone are fixed
it.skip("should setCode", async () => {
const code = fs.readFileSync(
path.join(__dirname, "../../../mock/rococo_runtime.compact.wasm")
).toString("hex");
await sudo(interBtcAPI, () => interBtcAPI.system.setCode(code));
});
});
Example #5
Source File: test-sudo.ts From moonbeam with GNU General Public License v3.0 | 6 votes |
describeDevMoonbeam("Sudo - Only sudo account - test gas", (context) => {
let alith: KeyringPair;
before("Setup genesis account for substrate", async () => {
const keyring = new Keyring({ type: "ethereum" });
alith = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
});
it("should NOT be able to call sudo with another account than sudo account", async function () {
await createBlockWithExtrinsic(
context,
alith,
context.polkadotApi.tx.sudo.sudo(
context.polkadotApi.tx.parachainStaking.setParachainBondAccount(GENESIS_ACCOUNT)
)
);
await verifyLatestBlockFees(context, expect);
});
});
Example #6
Source File: transferTokens.ts From community-repo with GNU General Public License v3.0 | 6 votes |
async getFaucetAccount(): Promise<NamedKeyringPair | null> {
const jsonBackupFilePath = `../../accounts/${process.env.ACCOUNT_JSON_NAME}`;
let accountJsonObj;
try {
accountJsonObj = require(jsonBackupFilePath);
} catch (e) {
console.error(
'Provided backup file is not valid or cannot be accessed'
);
throw new Error('Server error [1]');
}
const keyring = new Keyring();
let account: NamedKeyringPair;
try {
// Try adding and retrieving the keys in order to validate that the backup file is correct
keyring.addFromJson(accountJsonObj);
account = keyring.getPair(accountJsonObj.address) as NamedKeyringPair; // We can be sure it's named, because we forced it before
} catch (e) {
console.error('Provided backup file is not valid');
throw new Error('Server error [2]');
}
return account;
}
Example #7
Source File: test-balance-transfer-txwrapper-substrate.ts From moonbeam with GNU General Public License v3.0 | 5 votes |
describeDevMoonbeam("Balance transfer - txwrapper", (context) => {
before("Create block with transfer to test account of 512", async function () {
// txwrapper takes more time to initiate :/
this.timeout(10000);
const [
{ block },
blockHash,
genesisHash,
metadataRpc,
{ specVersion, transactionVersion, specName },
] = await Promise.all([
rpcToLocalNode(context.rpcPort, "chain_getBlock"),
rpcToLocalNode(context.rpcPort, "chain_getBlockHash"),
rpcToLocalNode(context.rpcPort, "chain_getBlockHash", [0]),
rpcToLocalNode(context.rpcPort, "state_getMetadata"),
rpcToLocalNode(context.rpcPort, "state_getRuntimeVersion"),
]);
const registry = getRegistry({
chainName: "Moonriver",
specName,
specVersion,
metadataRpc,
});
const unsigned = substrateMethods.balances.transfer(
{
dest: TEST_ACCOUNT,
value: 512,
},
{
address: GENESIS_ACCOUNT,
blockHash,
blockNumber: registry.createType("BlockNumber", block.header.number).toNumber(),
eraPeriod: 64,
genesisHash,
metadataRpc,
nonce: 0, // Assuming this is Gerald's first tx on the chain
specVersion,
tip: 0,
transactionVersion,
},
{
metadataRpc,
registry,
}
);
const signingPayload = createSigningPayload(unsigned, { registry });
const keyring = new Keyring({ type: "ethereum" });
const genesis = await keyring.addFromUri(GENESIS_ACCOUNT_PRIVATE_KEY, null, "ethereum");
const signature = signWith(genesis, signingPayload, {
metadataRpc,
registry,
});
// Serialize a signed transaction.
const tx = createSignedTx(unsigned, signature, { metadataRpc, registry });
await rpcToLocalNode(context.rpcPort, "author_submitExtrinsic", [tx]);
await context.createBlock();
});
it("should increase to account", async function () {
expect(await context.web3.eth.getBalance(TEST_ACCOUNT, 0)).to.equal("0");
expect(await context.web3.eth.getBalance(TEST_ACCOUNT, 1)).to.equal("512");
});
it("should reflect balance identically on polkadot/web3", async function () {
const block1Hash = await context.polkadotApi.rpc.chain.getBlockHash(1);
expect(await context.web3.eth.getBalance(GENESIS_ACCOUNT, 1)).to.equal(
(
(await context.polkadotApi.query.system.account.at(block1Hash, GENESIS_ACCOUNT)) as any
).data.free.toString()
);
});
it("should check fees", async function () {
await verifyLatestBlockFees(context, expect, BigInt(512));
});
});
Example #8
Source File: Keyring.ts From gear-js with GNU General Public License v3.0 | 5 votes |
static fromKeyPair(pair: Keypair, name?: string): KeyringPair {
const keyring = new Keyring({ type: 'sr25519' });
return GearKeyring.unlock(keyring.addFromPair(pair, { name }));
}
Example #9
Source File: test-runtime-upgrade.ts From moonbeam with GNU General Public License v3.0 | 5 votes |
describeParachain(
`Runtime upgrade ${RUNTIME_VERSION}`,
{
parachain: {
chain: "moonbase-local",
runtime: `runtime-${baseRuntime}`,
binary: "local",
},
relaychain: {
binary: "local",
},
},
(context) => {
if (localVersion !== alreadyReleased) {
it("should not fail", async function () {
// Expected to take 10 blocks for upgrade + 4 blocks to check =>
// ~200000 + init 60000 + error marging 140000
this.timeout(400000);
const keyring = new Keyring({ type: "ethereum" });
const alith = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
const currentVersion = await (
(await context.polkadotApiParaone.query.system.lastRuntimeUpgrade()) as any
).unwrap();
expect(currentVersion.toJSON()).to.deep.equal({
specVersion: Number(baseRuntime),
specName: "moonbase",
});
console.log(
`Current runtime: ✅ runtime ${currentVersion.specName.toString()} ` +
`${currentVersion.specVersion.toString()}`
);
await context.upgradeRuntime(alith, "moonbase", RUNTIME_VERSION);
process.stdout.write(`Checking on-chain runtime version ${localVersion}...`);
expect(
await (await context.polkadotApiParaone.query.system.lastRuntimeUpgrade()).toJSON()
).to.deep.equal({
specVersion: Number(localVersion),
specName: "moonbase",
});
process.stdout.write("✅\n");
process.stdout.write("Waiting extra block being produced...");
await context.waitBlocks(4); // Make sure the new runtime is producing blocks
process.stdout.write(`✅ total ${context.blockNumber} block produced\n`);
});
}
}
);
Example #10
Source File: index.tsx From crust-apps with Apache License 2.0 | 5 votes |
keyring = new Keyring()
Example #11
Source File: Keyring.ts From gear-js with GNU General Public License v3.0 | 5 votes |
static async fromSuri(suri: string, name?: string): Promise<KeyringPair> {
const keyring = new Keyring({ type: 'sr25519' });
await waitReady();
const keyPair = keyring.addFromUri(suri, { name });
return keyPair;
}
Example #12
Source File: test-crowdloan.ts From moonbeam with GNU General Public License v3.0 | 5 votes |
describeDevMoonbeam("Crowdloan", (context) => {
let sudoAccount: KeyringPair;
let numberOfAccounts: number = 1000; // min 2
let largInput: [string, string, bigint][];
before("Setup genesis account for substrate", async () => {
// We shouldnt be able to register as many accounts unless we do it in batches
numberOfAccounts = Number(
(await context.polkadotApi.consts.crowdloanRewards.maxInitContributors) as any
);
const keyring = new Keyring({ type: "ethereum" });
sudoAccount = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
});
it("should be able to register many accounts - batch : " + numberOfAccounts, async function () {
// should create a bunch of test eth accounts
this.timeout(20000);
let web3 = new Web3();
let accounts = new Array(numberOfAccounts).fill(0).map((_, i) => web3.eth.accounts.create());
largInput = accounts.map((acc: Account, i: number) => {
return [
acc.address + "111111111111111111111111",
acc.address,
(3_000_000n * GLMR) / BigInt(numberOfAccounts),
];
});
expect(largInput.length).to.eq(numberOfAccounts);
expect(largInput[0][1] !== largInput[numberOfAccounts - 1][1]).to.eq(true);
// should be able to register many accounts
await context.polkadotApi.tx.utility
.batch([
await context.polkadotApi.tx.sudo.sudo(
context.polkadotApi.tx.crowdloanRewards.initializeRewardVec(
largInput.slice(0, Math.floor(numberOfAccounts / 3))
)
),
await context.polkadotApi.tx.sudo.sudo(
context.polkadotApi.tx.crowdloanRewards.initializeRewardVec(
largInput.slice(
Math.floor(numberOfAccounts / 3),
Math.floor((numberOfAccounts * 2) / 3)
)
)
),
await context.polkadotApi.tx.sudo.sudo(
context.polkadotApi.tx.crowdloanRewards.initializeRewardVec(
largInput.slice(Math.floor((numberOfAccounts * 2) / 3), numberOfAccounts)
)
),
])
.signAndSend(sudoAccount);
await context.createBlock();
let initBlock = (await context.polkadotApi.query.crowdloanRewards.initRelayBlock()) as any;
// Complete initialization
await context.polkadotApi.tx.sudo
.sudo(
context.polkadotApi.tx.crowdloanRewards.completeInitialization(
initBlock.toBigInt() + VESTING_PERIOD
)
)
.signAndSend(sudoAccount);
await context.createBlock();
await Promise.all(
largInput.map(async (input) => {
expect((await getAccountPayable(context, input[1])).totalReward.toBigInt()).to.equal(
(3_000_000n * GLMR) / BigInt(numberOfAccounts)
);
})
);
});
});
Example #13
Source File: Keyring.ts From gear-js with GNU General Public License v3.0 | 5 votes |
static fromJson(keypairJson: KeyringPair$Json | string, passphrase?: string): KeyringPair {
const json: KeyringPair$Json = isString(keypairJson) ? JSON.parse(keypairJson) : keypairJson;
const keyring = new Keyring().addFromJson(json);
return GearKeyring.unlock(keyring, passphrase);
}
Example #14
Source File: shared.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
public keyring(useEd25519 = false) {
return new Keyring({
type: useEd25519 ? 'ed25519' : 'sr25519',
ss58Format: this._ss58Format,
});
}
Example #15
Source File: hrmp-setup.ts From interbtc-api with Apache License 2.0 | 5 votes |
async function main(): Promise<void> {
await cryptoWaitReady();
const keyring = new Keyring({ type: "sr25519" });
const userKeyring = keyring.addFromUri(ACCOUNT_URI);
const api = await createSubstrateAPI(PARACHAIN_ENDPOINT);
const parent = api.createType<XcmV1MultiLocation>("XcmV1MultiLocation", {
parents: 1,
interior: api.createType("XcmV1MultilocationJunctions", {
here: true
})
});
const setupTx = api.tx.sudo.sudo(api.tx.polkadotXcm.forceXcmVersion(parent, 2));
// transactions used for the purestake alpha test
const westendRequestXcmTx = construct_xcm(api, 1002, "0x3300e80300000800000000040000");
const westendCancelXcmTx = construct_xcm(api, 1002, "0x3306ea030000e9030000");
const westendAcceptXcmTx = construct_xcm(api, 1002, "0x3301e8030000");
// transactions used for rococo-local test
const rococoRequestXcmTx = construct_xcm(api, 2000, "0x1700b80b00000800000000900100");
const rococoAcceptXcmTx = construct_xcm(api, 2000, "0x1701d0070000");
// transactions to be used on kintsugi
const kinstugiRequestXcmTx = construct_xcm(api, 2092, "0x3c00d0070000e803000000900100");
// note: very important to use `.method`, otherwise it includes signing info. The polkadot.js
// app strips the signing info when you try to decode it, but if you use the call data in
// an extrinsic (e.g. in democracy), it will fail.
console.log("Call data: " + rococoRequestXcmTx.method.toHex());
console.log("Call hash: " + rococoRequestXcmTx.method.hash.toHex());
const transactionAPI = new DefaultTransactionAPI(api, userKeyring);
console.log("Constructed the tx, broadcasting first...");
await transactionAPI.sendLogged(setupTx, undefined);
console.log("broadcasting second...");
await transactionAPI.sendLogged(api.tx.sudo.sudo(rococoAcceptXcmTx), undefined);
api.disconnect();
}
Example #16
Source File: rpc.ts From polkadot-launch with MIT License | 5 votes |
// Submit an extrinsic to the relay chain to register a parachain.
// Uses the Alice account which is known to be Sudo for the relay chain.
export async function registerParachain(
api: ApiPromise,
id: string,
wasm: string,
header: string,
finalization: boolean = false
) {
return new Promise<void>(async (resolvePromise, reject) => {
await cryptoWaitReady();
const keyring = new Keyring({ type: "sr25519" });
const alice = keyring.addFromUri("//Alice");
let paraGenesisArgs = {
genesis_head: header,
validation_code: wasm,
parachain: true,
};
let genesis = api.createType("ParaGenesisArgs", paraGenesisArgs);
const nonce = Number((await api.query.system.account(alice.address)).nonce);
console.log(
`--- Submitting extrinsic to register parachain ${id}. (nonce: ${nonce}) ---`
);
const unsub = await api.tx.sudo
.sudo(api.tx.parasSudoWrapper.sudoScheduleParaInitialize(id, genesis))
.signAndSend(alice, { nonce: nonce, era: 0 }, (result) => {
console.log(`Current status is ${result.status}`);
if (result.status.isInBlock) {
console.log(
`Transaction included at blockHash ${result.status.asInBlock}`
);
if (finalization) {
console.log("Waiting for finalization...");
} else {
unsub();
resolvePromise();
}
} else if (result.status.isFinalized) {
console.log(
`Transaction finalized at blockHash ${result.status.asFinalized}`
);
unsub();
resolvePromise();
} else if (result.isError) {
console.log(`Transaction Error`);
reject(`Transaction Error`);
}
});
});
}
Example #17
Source File: test-crowdloan.ts From moonbeam with GNU General Public License v3.0 | 5 votes |
describeDevMoonbeam("Crowdloan", (context) => {
let genesisAccount: KeyringPair, sudoAccount: KeyringPair;
before("Setup genesis account for substrate", async () => {
const keyring = new Keyring({ type: "ethereum" });
genesisAccount = await keyring.addFromUri(GENESIS_ACCOUNT_PRIVATE_KEY, null, "ethereum");
sudoAccount = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
});
it("should check initial state", async function () {
// check that genesis has genesis balance
expect(Number(await context.web3.eth.getBalance(GENESIS_ACCOUNT))).to.eq(
Number(GENESIS_ACCOUNT_BALANCE)
);
// check that genesis is not registered
const isPayable = await getAccountPayable(context, GENESIS_ACCOUNT);
expect(isPayable).to.equal(null);
});
it("should be able to register the genesis account for reward", async function () {
// should be able to register the genesis account for reward
await context.polkadotApi.tx.sudo
.sudo(
context.polkadotApi.tx.crowdloanRewards.initializeRewardVec([
[relayChainAddress, GENESIS_ACCOUNT, 3_000_000n * GLMR],
])
)
.signAndSend(sudoAccount);
await context.createBlock();
await verifyLatestBlockFees(context, expect, 3_000_000n);
let initBlock = (await context.polkadotApi.query.crowdloanRewards.initRelayBlock()) as any;
// Complete initialization
await context.polkadotApi.tx.sudo
.sudo(
context.polkadotApi.tx.crowdloanRewards.completeInitialization(
initBlock.toBigInt() + VESTING_PERIOD
)
)
.signAndSend(sudoAccount);
await context.createBlock();
expect((await getAccountPayable(context, GENESIS_ACCOUNT)).totalReward.toBigInt()).to.equal(
3_000_000n * GLMR
);
let isInitialized = await context.polkadotApi.query.crowdloanRewards.initialized();
expect(isInitialized.toHuman()).to.be.true;
});
});
Example #18
Source File: initialize.test.ts From interbtc-api with Apache License 2.0 | 4 votes |
describe("Initialize parachain state", () => {
let api: ApiPromise;
let userInterBtcAPI: InterBtcApi;
let sudoInterBtcAPI: InterBtcApi;
let bitcoinCoreClient: BitcoinCoreClient;
let keyring: Keyring;
let sudoAccount: KeyringPair;
let userAccount: KeyringPair;
let vault_1: KeyringPair;
let vault_2: KeyringPair;
let vault_3: KeyringPair;
let vault_to_ban: KeyringPair;
let vault_to_liquidate: KeyringPair;
let wrappedCurrency: WrappedCurrency;
let collateralCurrency: CollateralCurrency;
function accountIdFromKeyring(keyPair: KeyringPair): AccountId {
return newAccountId(api, keyPair.address);
}
async function waitForRegister(api: VaultsAPI, accountId: AccountId, collateralCurrency: CurrencyIdLiteral) {
while (true) {
try {
await api.get(accountId, collateralCurrency);
return;
} catch (e) { console.log(e); }
await sleep(SLEEP_TIME_MS);
}
}
before(async function () {
api = await createSubstrateAPI(PARACHAIN_ENDPOINT);
keyring = new Keyring({ type: "sr25519" });
sudoAccount = keyring.addFromUri(SUDO_URI);
userAccount = keyring.addFromUri(USER_1_URI);
vault_1 = keyring.addFromUri(VAULT_1_URI);
vault_2 = keyring.addFromUri(VAULT_2_URI);
vault_3 = keyring.addFromUri(VAULT_3_URI);
vault_to_ban = keyring.addFromUri(VAULT_TO_BAN_URI);
vault_to_liquidate = keyring.addFromUri(VAULT_TO_LIQUIDATE_URI);
bitcoinCoreClient = new BitcoinCoreClient(
BITCOIN_CORE_NETWORK,
BITCOIN_CORE_HOST,
BITCOIN_CORE_USERNAME,
BITCOIN_CORE_PASSWORD,
BITCOIN_CORE_PORT,
BITCOIN_CORE_WALLET
);
userInterBtcAPI = new DefaultInterBtcApi(api, "regtest", userAccount, ESPLORA_BASE_PATH);
sudoInterBtcAPI = new DefaultInterBtcApi(api, "regtest", sudoAccount, ESPLORA_BASE_PATH);
wrappedCurrency = userInterBtcAPI.getWrappedCurrency();
collateralCurrency = getCorrespondingCollateralCurrency(userInterBtcAPI.getGovernanceCurrency());
const collateralCurrencyLiteral = tickerToCurrencyIdLiteral(collateralCurrency.ticker);
const vaultCollateralPairs: [KeyringPair, CurrencyIdLiteral][] = [
[vault_1, collateralCurrencyLiteral],
[vault_2, collateralCurrencyLiteral],
[vault_3, collateralCurrencyLiteral],
[vault_to_ban, collateralCurrencyLiteral],
[vault_to_liquidate, collateralCurrencyLiteral]
];
// wait for all vaults to register
await Promise.all(
vaultCollateralPairs
.map(([keyring, collateral]): [AccountId, CurrencyIdLiteral] => [accountIdFromKeyring(keyring), collateral])
.map(([accountId, collateral]) => waitForRegister(userInterBtcAPI.vaults, accountId, collateral))
);
});
after(async () => {
api.disconnect();
});
it("should set the stable confirmations and ready the BTC-Relay", async () => {
// Speed up the process by only requiring 0 parachain and 0 bitcoin confirmations
const stableBitcoinConfirmationsToSet = 0;
const stableParachainConfirmationsToSet = 0;
let [stableBitcoinConfirmations, stableParachainConfirmations] = await Promise.all([
userInterBtcAPI.btcRelay.getStableBitcoinConfirmations(),
userInterBtcAPI.btcRelay.getStableParachainConfirmations()
]);
if (stableBitcoinConfirmations != 0 || stableParachainConfirmations != 0) {
await initializeStableConfirmations(
api,
{
bitcoinConfirmations: stableBitcoinConfirmationsToSet,
parachainConfirmations: stableParachainConfirmationsToSet
},
sudoAccount,
bitcoinCoreClient
);
[stableBitcoinConfirmations, stableParachainConfirmations] = await Promise.all([
userInterBtcAPI.btcRelay.getStableBitcoinConfirmations(),
userInterBtcAPI.btcRelay.getStableParachainConfirmations()
]);
}
assert.equal(stableBitcoinConfirmationsToSet, stableBitcoinConfirmations, "Setting the Bitcoin confirmations failed");
assert.equal(stableParachainConfirmationsToSet, stableParachainConfirmations, "Setting the Parachain confirmations failed");
});
it("should set the exchange rate", async () => {
async function setCollateralExchangeRate<C extends CollateralUnit>(value: Big, currency: Currency<C>) {
const exchangeRate = new ExchangeRate<Bitcoin, BitcoinUnit, typeof currency, typeof currency.units>(Bitcoin, currency, value);
// result will be medianized
await initializeExchangeRate(exchangeRate, sudoInterBtcAPI.oracle);
}
const exchangeRateValue = new Big("3855.23187");
await setCollateralExchangeRate(exchangeRateValue, Polkadot);
await setCollateralExchangeRate(exchangeRateValue, Kusama);
});
it("should set BTC tx fees", async () => {
const setFeeEstimate = new Big(1);
let getFeeEstimate = await sudoInterBtcAPI.oracle.getBitcoinFees();
if (!getFeeEstimate) {
await initializeBtcTxFees(setFeeEstimate, sudoInterBtcAPI.oracle);
// just check that this is set since we medianize results
getFeeEstimate = await sudoInterBtcAPI.oracle.getBitcoinFees();
}
assert.isDefined(getFeeEstimate);
});
it("should enable vault nomination", async () => {
let isNominationEnabled = await sudoInterBtcAPI.nomination.isNominationEnabled();
if (!isNominationEnabled) {
await initializeVaultNomination(true, sudoInterBtcAPI.nomination);
isNominationEnabled = await sudoInterBtcAPI.nomination.isNominationEnabled();
}
assert.isTrue(isNominationEnabled);
});
it("should issue 0.00007 wrapped", async () => {
const wrappedToIssue = newMonetaryAmount(0.00007, wrappedCurrency, true);
const feesToPay = await userInterBtcAPI.issue.getFeesToPay(wrappedToIssue);
const userAccountId = newAccountId(api, userAccount.address);
const userWrappedBefore = (await userInterBtcAPI.tokens.balance(wrappedCurrency, userAccountId)).free;
await initializeIssue(
userInterBtcAPI, bitcoinCoreClient, userAccount, wrappedToIssue, newVaultId(api, vault_1.address, collateralCurrency, wrappedCurrency)
);
const collateralCurrencyLiteral = tickerToCurrencyIdLiteral(collateralCurrency.ticker);
const [userWrappedAfter, totalIssuance, vaultIssuedAmount] = await Promise.all([
userInterBtcAPI.tokens.balance(wrappedCurrency, userAccountId),
userInterBtcAPI.tokens.total(wrappedCurrency),
userInterBtcAPI.vaults.getIssuedAmount(newAccountId(api, vault_1.address), collateralCurrencyLiteral)
]);
assert.equal(
userWrappedBefore.add(wrappedToIssue).sub(feesToPay).toString(),
userWrappedAfter.free.toString(),
"Issued amount is different from the requested amount"
);
// TODO: get the total issuance and vault issued amount before and calculate difference
// so that this test can be run more than once without resetting the chain
// assert.equal(totalIssuance.toString(), wrappedToIssue.toString());
// assert.equal(vaultIssuedAmount.toString(), wrappedToIssue.toString());
});
it("should redeem 0.00005 InterBtc", async () => {
const wrappedToRedeem = newMonetaryAmount(0.00005, wrappedCurrency, true);
const redeemAddress = "bcrt1qed0qljupsmqhxul67r7358s60reqa2qtte0kay";
await userInterBtcAPI.redeem.request(wrappedToRedeem, redeemAddress);
const redeemRequests = await userInterBtcAPI.redeem.list();
assert.isAtLeast(
redeemRequests.length,
1,
"Error in initialization setup. Should have at least 1 redeem request"
);
});
});
Example #19
Source File: test-crowdloan.ts From moonbeam with GNU General Public License v3.0 | 4 votes |
describeDevMoonbeam("Crowdloan", (context) => {
let sudoAccount: KeyringPair;
before("Setup genesis account for substrate", async () => {
const keyring = new Keyring({ type: "ethereum" });
sudoAccount = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
});
it("should be able to initialize through democracy", async function () {
let calls = [];
// We are gonna put the initialization and completion in a batch_all utility call
calls.push(
context.polkadotApi.tx.crowdloanRewards.initializeRewardVec([
[relayChainAddress, GENESIS_ACCOUNT, 1_500_000n * GLMR],
[relayChainAddress_2, null, 1_500_000n * GLMR],
])
);
let initBlock = (await context.polkadotApi.query.crowdloanRewards.initRelayBlock()) as any;
calls.push(
context.polkadotApi.tx.crowdloanRewards.completeInitialization(
initBlock.toBigInt() + VESTING_PERIOD
)
);
// Here we build the utility call
const proposal = context.polkadotApi.tx.utility.batchAll(calls);
// We encode the proposal
let encodedProposal = (proposal as SubmittableExtrinsic)?.method.toHex() || "";
let encodedHash = blake2AsHex(encodedProposal);
// Submit the pre-image
await context.polkadotApi.tx.democracy.notePreimage(encodedProposal).signAndSend(sudoAccount);
await context.createBlock();
// Propose
await context.polkadotApi.tx.democracy
.propose(encodedHash, 1000n * GLMR)
.signAndSend(sudoAccount);
await context.createBlock();
const publicPropCount = await context.polkadotApi.query.democracy.publicPropCount();
// we only use sudo to enact the proposal
await context.polkadotApi.tx.sudo
.sudoUncheckedWeight(
context.polkadotApi.tx.democracy.enactProposal(encodedHash, publicPropCount),
1
)
.signAndSend(sudoAccount);
await context.createBlock();
let isInitialized = await context.polkadotApi.query.crowdloanRewards.initialized();
expect(isInitialized.toHuman()).to.be.true;
// Get reward info of associated
let reward_info_associated = await getAccountPayable(context, GENESIS_ACCOUNT);
// Get reward info of unassociated
let reward_info_unassociated = (
(await context.polkadotApi.query.crowdloanRewards.unassociatedContributions(
relayChainAddress_2
)) as any
).unwrap();
// Check payments
expect(reward_info_associated.totalReward.toBigInt()).to.equal(1_500_000n * GLMR);
expect(reward_info_associated.claimedReward.toBigInt()).to.equal(450_000n * GLMR);
expect(reward_info_unassociated.totalReward.toBigInt()).to.equal(1_500_000n * GLMR);
expect(reward_info_unassociated.claimedReward.toBigInt()).to.equal(0n);
// check balances
const account = (await context.polkadotApi.query.system.account(GENESIS_ACCOUNT)) as any;
expect(account.data.free.toBigInt() - GENESIS_ACCOUNT_BALANCE).to.equal(
reward_info_associated.claimedReward.toBigInt()
);
});
});
Example #20
Source File: tokens.test.ts From interbtc-api with Apache License 2.0 | 4 votes |
describe("TokensAPI", () => {
let api: ApiPromise;
let user1Account: KeyringPair;
let user2Account: KeyringPair;
let interBtcAPI: InterBtcApi;
before(async () => {
api = await createSubstrateAPI(PARACHAIN_ENDPOINT);
const keyring = new Keyring({ type: "sr25519" });
user1Account = keyring.addFromUri(USER_1_URI);
user2Account = keyring.addFromUri(USER_2_URI);
interBtcAPI = new DefaultInterBtcApi(api, "regtest", user1Account, ESPLORA_BASE_PATH);
});
after(() => {
return api.disconnect();
});
it("should subscribe to balance updates", async () => {
for (const currency of [...CollateralCurrency]) {
await testBalanceSubscription(currency as Currency<CurrencyUnit>);
}
});
async function testBalanceSubscription<U extends CurrencyUnit>(currency: Currency<U>): Promise<void> {
// Subscribe and receive two balance updates
let updatedBalance = new ChainBalance<U>(currency);
let updatedAccount = "";
function balanceUpdateCallback(account: string, newBalance: ChainBalance<U>) {
updatedBalance = newBalance;
updatedAccount = account;
}
const amountToUpdateUser2sAccountBy = newMonetaryAmount(10, currency, true);
const user2BalanceBeforeTransfer =
await interBtcAPI.tokens.balance<typeof currency.units>(currency, newAccountId(api, user2Account.address));
const unsubscribe = await interBtcAPI.tokens.subscribeToBalance(currency, user2Account.address, balanceUpdateCallback);
// Send the first transfer, expect the callback to be called with correct values
await interBtcAPI.tokens.transfer(user2Account.address, amountToUpdateUser2sAccountBy);
assert.equal(updatedAccount, user2Account.address);
const expectedUser2BalanceAfterFirstTransfer = new ChainBalance<U>(
currency,
user2BalanceBeforeTransfer.free.add(amountToUpdateUser2sAccountBy).toBig(),
user2BalanceBeforeTransfer.transferable.add(amountToUpdateUser2sAccountBy).toBig(),
user2BalanceBeforeTransfer.reserved.toBig()
);
assert.equal(updatedBalance.toString(), expectedUser2BalanceAfterFirstTransfer.toString());
// Send the second transfer, expect the callback to be called with correct values
await interBtcAPI.tokens.transfer(user2Account.address, amountToUpdateUser2sAccountBy);
assert.equal(updatedAccount, user2Account.address);
const expectedUser2BalanceAfterSecondTransfer = new ChainBalance<U>(
currency,
expectedUser2BalanceAfterFirstTransfer.free.add(amountToUpdateUser2sAccountBy).toBig(),
expectedUser2BalanceAfterFirstTransfer.transferable.add(amountToUpdateUser2sAccountBy).toBig(),
expectedUser2BalanceAfterFirstTransfer.reserved.toBig()
);
assert.equal(updatedBalance.toString(), expectedUser2BalanceAfterSecondTransfer.toString());
// TODO: Commented out because it blocks release, fix.
// Fails because it conflicts with the escrowAPI test:
// Error: tokens.LiquidityRestrictions Failed because liquidity restrictions due to locking
// if (currency.name === Interlay.name) {
// const currentBlockNumber = await interBtcAPI.system.getCurrentBlockNumber();
// const unlockHeightDiff = (await escrowAPI.getSpan()).toNumber();
// const amountToFreeze = newMonetaryAmount(600, currency as Currency<U>, true);
// await escrowAPI.createLock(
// amountToFreeze as unknown as MonetaryAmount<Currency<GovernanceUnit>, GovernanceUnit>,
// currentBlockNumber + unlockHeightDiff
// );
// const expectedUser2BalanceAfterEscrowLock = new ChainBalance<U>(
// currency,
// expectedUser2BalanceAfterSecondTransfer.free.toBig(),
// expectedUser2BalanceAfterSecondTransfer.transferable.sub(amountToFreeze).toBig(),
// expectedUser2BalanceAfterSecondTransfer.reserved.toBig()
// );
// assert.equal(updatedAccount, user2Account.address);
// assert.equal(updatedBalance.toString(), expectedUser2BalanceAfterEscrowLock.toString());
// }
unsubscribe();
}
});
Example #21
Source File: test-precompile-democracy.ts From moonbeam with GNU General Public License v3.0 | 4 votes |
describeDevMoonbeam("Democracy - vote on referendum", (context) => {
let genesisAccount: KeyringPair, alith: KeyringPair;
let encodedHash: `0x${string}`;
let enactmentPeriod, votingPeriod;
let iFace: Interface;
before("Setup genesis account for substrate", async () => {
const keyring = new Keyring({ type: "ethereum" });
genesisAccount = await keyring.addFromUri(GENESIS_ACCOUNT_PRIVATE_KEY, null, "ethereum");
alith = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
iFace = await deployAndInterfaceContract(context, "Democracy");
// enactmentPeriod
enactmentPeriod = await context.polkadotApi.consts.democracy.enactmentPeriod;
// votingPeriod
votingPeriod = await context.polkadotApi.consts.democracy.votingPeriod;
// encodedHash
encodedHash = await notePreimagePrecompile(
context,
iFace,
context.polkadotApi.tx.parachainStaking.setParachainBondAccount(GENESIS_ACCOUNT)
);
// propose
await sendPrecompileTx(
context,
ADDRESS_DEMO_PRECOMPILE,
SELECTORS,
GENESIS_ACCOUNT,
GENESIS_ACCOUNT_PRIVATE_KEY,
"propose",
[encodedHash, numberToHex(Number(PROPOSAL_AMOUNT))]
);
// second
await sendPrecompileTx(
context,
ADDRESS_DEMO_PRECOMPILE,
SELECTORS,
ALITH,
ALITH_PRIV_KEY,
"second",
[numberToHex(0), numberToHex(1000)]
);
});
it("check enactment period", async function () {
// enactmentPeriod
expect(enactmentPeriod.toHuman()).to.equal("7,200");
});
it("check voting Period", async function () {
// votingPeriod
expect(votingPeriod.toHuman()).to.equal("36,000");
});
it("vote", async function () {
this.timeout(2000000);
// let Launchperiod elapse to turn the proposal into a referendum
// launchPeriod minus the 3 blocks that already elapsed
for (let i = 0; i < 7200 - 3; i++) {
await context.createBlock();
}
// vote
await sendPrecompileTx(
context,
ADDRESS_DEMO_PRECOMPILE,
SELECTORS,
ALITH,
ALITH_PRIV_KEY,
"standard_vote",
[numberToHex(0), "0x01", numberToHex(Number(VOTE_AMOUNT)), numberToHex(1)]
);
// referendumInfoOf
const referendumInfoOf = await context.polkadotApi.query.democracy.referendumInfoOf(0);
console.log("referendumInfoOf.toHuman() ", referendumInfoOf.toHuman());
expect((referendumInfoOf.toHuman() as any).Ongoing.proposalHash).to.equal(encodedHash);
expect((referendumInfoOf.toHuman() as any).Ongoing.tally.ayes).to.equal(
"10,000,000,000,000,000,000"
);
expect((referendumInfoOf.toHuman() as any).Ongoing.tally.turnout).to.equal(
"10,000,000,000,000,000,000"
);
// let votePeriod + enactmentPeriod elapse to turn the proposal into a referendum
for (let i = 0; i < Number(votingPeriod) + Number(enactmentPeriod) + 10; i++) {
await context.createBlock();
}
let parachainBondInfo = await context.polkadotApi.query.parachainStaking.parachainBondInfo();
expect(parachainBondInfo.toHuman()["account"]).to.equal(GENESIS_ACCOUNT);
});
});
Example #22
Source File: App.tsx From interbtc-ui with Apache License 2.0 | 4 votes |
App = (): JSX.Element => {
const {
bridgeLoaded,
address,
wrappedTokenBalance,
wrappedTokenTransferableBalance,
collateralTokenBalance,
collateralTokenTransferableBalance,
governanceTokenBalance,
governanceTokenTransferableBalance,
prices
} = useSelector((state: StoreType) => state.general);
// eslint-disable-next-line max-len
const [bridgeStatus, setBridgeStatus] = React.useState(STATUSES.IDLE); // TODO: `bridgeLoaded` should be based on enum instead of boolean
const dispatch = useDispatch();
// Loads the main bridge API - connection to the bridge
const loadBridge = React.useCallback(async (): Promise<void> => {
try {
setBridgeStatus(STATUSES.PENDING);
window.bridge = await createInterBtcApi(constants.PARACHAIN_URL, constants.BITCOIN_NETWORK);
dispatch(isBridgeLoaded(true));
setBridgeStatus(STATUSES.RESOLVED);
} catch (error) {
toast.warn('Unable to connect to the BTC-Parachain.');
console.log('[loadBridge] error.message => ', error.message);
setBridgeStatus(STATUSES.REJECTED);
}
}, [dispatch]);
// Loads the connection to the faucet - only for testnet purposes
const loadFaucet = React.useCallback(async (): Promise<void> => {
try {
window.faucet = new FaucetClient(window.bridge.api, constants.FAUCET_URL);
dispatch(isFaucetLoaded(true));
} catch (error) {
console.log('[loadFaucet] error.message => ', error.message);
}
}, [dispatch]);
// Loads the bridge
React.useEffect(() => {
if (bridgeLoaded) return; // Not necessary but for more clarity
if (bridgeStatus !== STATUSES.IDLE) return;
(async () => {
try {
await loadBridge();
} catch (error) {
console.log('[App React.useEffect 7] error.message => ', error.message);
}
})();
}, [loadBridge, bridgeLoaded, bridgeStatus]);
// Loads the faucet
React.useEffect(() => {
if (!bridgeLoaded) return;
if (process.env.REACT_APP_BITCOIN_NETWORK === BitcoinNetwork.Mainnet) return;
(async () => {
try {
await loadFaucet();
} catch (error) {
console.log('[App React.useEffect 8] error.message => ', error.message);
}
})();
}, [bridgeLoaded, loadFaucet]);
// Maybe loads the vault client - only if the current address is also registered as a vault
React.useEffect(() => {
if (!bridgeLoaded) return;
if (!address) return;
const id = window.bridge.api.createType(ACCOUNT_ID_TYPE_NAME, address);
(async () => {
try {
dispatch(isVaultClientLoaded(false));
const vault = await window.bridge.vaults.get(id, COLLATERAL_TOKEN_ID_LITERAL);
dispatch(isVaultClientLoaded(!!vault));
} catch (error) {
// TODO: should add error handling
console.log('[App React.useEffect 1] error.message => ', error.message);
}
})();
}, [bridgeLoaded, address, dispatch]);
// Initializes data on app bootstrap
React.useEffect(() => {
if (!dispatch) return;
if (!bridgeLoaded) return;
(async () => {
try {
const [
totalWrappedTokenAmount,
totalLockedCollateralTokenAmount,
totalGovernanceTokenAmount,
btcRelayHeight,
bitcoinHeight,
state
] = await Promise.all([
window.bridge.tokens.total(WRAPPED_TOKEN),
window.bridge.tokens.total(COLLATERAL_TOKEN),
window.bridge.tokens.total(GOVERNANCE_TOKEN),
window.bridge.btcRelay.getLatestBlockHeight(),
window.bridge.electrsAPI.getLatestBlockHeight(),
window.bridge.system.getStatusCode()
]);
const parachainStatus = (state: SecurityStatusCode) => {
if (state.isError) {
return ParachainStatus.Error;
} else if (state.isRunning) {
return ParachainStatus.Running;
} else if (state.isShutdown) {
return ParachainStatus.Shutdown;
} else {
return ParachainStatus.Loading;
}
};
dispatch(
initGeneralDataAction(
totalWrappedTokenAmount,
totalLockedCollateralTokenAmount,
totalGovernanceTokenAmount,
Number(btcRelayHeight),
bitcoinHeight,
parachainStatus(state)
)
);
} catch (error) {
// TODO: should add error handling
console.log('[App React.useEffect 2] error.message => ', error.message);
}
})();
}, [dispatch, bridgeLoaded]);
// Loads the address for the currently selected account
React.useEffect(() => {
if (!dispatch) return;
if (!bridgeLoaded) return;
const trySetDefaultAccount = () => {
if (constants.DEFAULT_ACCOUNT_SEED) {
const keyring = new Keyring({ type: 'sr25519', ss58Format: constants.SS58_FORMAT });
const defaultAccountKeyring = keyring.addFromUri(constants.DEFAULT_ACCOUNT_SEED as string);
window.bridge.setAccount(defaultAccountKeyring);
dispatch(changeAddressAction(defaultAccountKeyring.address));
}
};
(async () => {
try {
const theExtensions = await web3Enable(APP_NAME);
if (theExtensions.length === 0) {
trySetDefaultAccount();
return;
}
dispatch(setInstalledExtensionAction(theExtensions.map((extension) => extension.name)));
// TODO: load accounts just once
const accounts = await web3Accounts({ ss58Format: constants.SS58_FORMAT });
const matchedAccount = accounts.find((account) => account.address === address);
if (matchedAccount) {
const { signer } = await web3FromAddress(address);
window.bridge.setAccount(address, signer);
dispatch(changeAddressAction(address));
} else {
dispatch(changeAddressAction(''));
window.bridge.removeAccount();
}
} catch (error) {
// TODO: should add error handling
console.log('[App React.useEffect 3] error.message => ', error.message);
}
})();
}, [address, bridgeLoaded, dispatch]);
// Subscribes to balances
React.useEffect(() => {
if (!dispatch) return;
if (!bridgeLoaded) return;
if (!address) return;
let unsubscribeFromCollateral: () => void;
let unsubscribeFromWrapped: () => void;
let unsubscribeFromGovernance: () => void;
(async () => {
try {
unsubscribeFromCollateral = await window.bridge.tokens.subscribeToBalance(
COLLATERAL_TOKEN,
address,
(_: string, balance: ChainBalance<CollateralUnit>) => {
if (!balance.free.eq(collateralTokenBalance)) {
dispatch(updateCollateralTokenBalanceAction(balance.free));
}
if (!balance.transferable.eq(collateralTokenTransferableBalance)) {
dispatch(updateCollateralTokenTransferableBalanceAction(balance.transferable));
}
}
);
} catch (error) {
console.log('[App React.useEffect 4] error.message => ', error.message);
}
})();
(async () => {
try {
unsubscribeFromWrapped = await window.bridge.tokens.subscribeToBalance(
WRAPPED_TOKEN,
address,
(_: string, balance: ChainBalance<BitcoinUnit>) => {
if (!balance.free.eq(wrappedTokenBalance)) {
dispatch(updateWrappedTokenBalanceAction(balance.free));
}
if (!balance.transferable.eq(wrappedTokenTransferableBalance)) {
dispatch(updateWrappedTokenTransferableBalanceAction(balance.transferable));
}
}
);
} catch (error) {
console.log('[App React.useEffect 5] error.message => ', error.message);
}
})();
(async () => {
try {
unsubscribeFromGovernance = await window.bridge.tokens.subscribeToBalance(
GOVERNANCE_TOKEN,
address,
(_: string, balance: ChainBalance<GovernanceUnit>) => {
if (!balance.free.eq(governanceTokenBalance)) {
dispatch(updateGovernanceTokenBalanceAction(balance.free));
}
if (!balance.transferable.eq(governanceTokenTransferableBalance)) {
dispatch(updateGovernanceTokenTransferableBalanceAction(balance.transferable));
}
}
);
} catch (error) {
console.log('[App React.useEffect 6] error.message => ', error.message);
}
})();
return () => {
if (unsubscribeFromCollateral) {
unsubscribeFromCollateral();
}
if (unsubscribeFromWrapped) {
unsubscribeFromWrapped();
}
if (unsubscribeFromGovernance) {
unsubscribeFromGovernance();
}
};
}, [
dispatch,
bridgeLoaded,
address,
wrappedTokenBalance,
wrappedTokenTransferableBalance,
collateralTokenBalance,
collateralTokenTransferableBalance,
governanceTokenBalance,
governanceTokenTransferableBalance
]);
// Color schemes according to Interlay vs. Kintsugi
React.useEffect(() => {
if (process.env.REACT_APP_RELAY_CHAIN_NAME === POLKADOT) {
document.documentElement.classList.add(CLASS_NAMES.LIGHT);
document.documentElement.classList.remove(CLASS_NAMES.DARK);
document.body.classList.add('text-interlayTextPrimaryInLightMode');
document.body.classList.add('bg-interlayHaiti-50');
document.body.classList.add('theme-interlay');
}
// MEMO: should check dark mode as well
if (process.env.REACT_APP_RELAY_CHAIN_NAME === KUSAMA) {
// MEMO: inspired by https://tailwindcss.com/docs/dark-mode#toggling-dark-mode-manually
document.documentElement.classList.add(CLASS_NAMES.DARK);
document.documentElement.classList.remove(CLASS_NAMES.LIGHT);
document.body.classList.add('dark:text-kintsugiTextPrimaryInDarkMode');
document.body.classList.add('dark:bg-kintsugiMidnight-900');
document.body.classList.add('theme-kintsugi');
}
}, []);
// Keeps fetching live data prices
const { error: pricesError } = useQuery(
PRICES_URL,
async () => {
const response = await fetch(PRICES_URL);
if (!response.ok) {
throw new Error('Network response for prices was not ok.');
}
const newPrices = await response.json();
// Update the store only if the price is actually changed
if (
newPrices.bitcoin?.usd !== prices.bitcoin?.usd ||
newPrices[RELAY_CHAIN_NAME]?.usd !== prices.collateralToken?.usd ||
newPrices[BRIDGE_PARACHAIN_NAME]?.usd !== prices.governanceToken?.usd
) {
dispatch(
updateOfPricesAction({
bitcoin: newPrices.bitcoin,
collateralToken: newPrices[RELAY_CHAIN_NAME],
governanceToken: newPrices[BRIDGE_PARACHAIN_NAME]
})
);
}
},
{ refetchInterval: 60000 }
);
useErrorHandler(pricesError);
return (
<>
<InterlayHelmet />
<ToastContainer position='top-right' autoClose={5000} hideProgressBar={false} />
<Layout>
<Route
render={({ location }) => (
<React.Suspense fallback={<FullLoadingSpinner />}>
<Switch location={location}>
<Route exact path={PAGES.VAULTS}>
<Vaults />
</Route>
<Route exact path={PAGES.VAULT}>
<Vault />
</Route>
<Route path={PAGES.VAULT}>
<Vaults />
</Route>
<Route path={PAGES.DASHBOARD}>
<Dashboard />
</Route>
<Route path={PAGES.STAKING}>
<Staking />
</Route>
<Route path={PAGES.TRANSACTIONS}>
<Transactions />
</Route>
<Route path={PAGES.BRIDGE}>
<Bridge />
</Route>
<Route path={PAGES.TRANSFER}>
<Transfer />
</Route>
<Redirect exact from={PAGES.HOME} to={PAGES.BRIDGE} />
<Route path='*'>
<NoMatch />
</Route>
</Switch>
</React.Suspense>
)}
/>
</Layout>
</>
);
}
Example #23
Source File: index.ts From parachain-launch with Apache License 2.0 | 4 votes |
generateRelaychainGenesisFile = (config: Config, path: string, output: string) => {
const relaychain = config.relaychain;
if (!relaychain) {
return fatal('Missing relaychain');
}
if (!relaychain.chain) {
return fatal('Missing relaychain.chain');
}
if (!relaychain.image) {
return fatal('Missing relaychain.image');
}
const spec = getChainspec(relaychain.image, relaychain.chain);
// clear authorities
const runtime = spec.genesis.runtime.runtime_genesis_config || spec.genesis.runtime;
const sessionKeys = runtime.session.keys;
sessionKeys.length = 0;
// add authorities from config
const keyring = new Keyring();
for (const { name } of config.relaychain.nodes) {
const srAcc = keyring.createFromUri(`//${_.startCase(name)}`, undefined, 'sr25519');
const srStash = keyring.createFromUri(`//${_.startCase(name)}//stash`, undefined, 'sr25519');
const edAcc = keyring.createFromUri(`//${_.startCase(name)}`, undefined, 'ed25519');
const ecAcc = keyring.createFromUri(`//${_.startCase(name)}`, undefined, 'ecdsa');
const key = [
srStash.address,
srStash.address,
{
grandpa: edAcc.address,
babe: srAcc.address,
im_online: srAcc.address,
parachain_validator: srAcc.address,
authority_discovery: srAcc.address,
para_validator: srAcc.address,
para_assignment: srAcc.address,
beefy: encodeAddress(ecAcc.publicKey),
},
];
sessionKeys.push(key);
}
// additional patches
if (config.relaychain.runtimeGenesisConfig) {
const hrmp = config.relaychain.runtimeGenesisConfig.hrmp;
if (hrmp) {
hrmp.preopenHrmpChannels = hrmp.preopenHrmpChannels.map((channel) => {
if (!Array.isArray(channel)) {
return [channel.sender, channel.recipient, channel.maxCapacity, channel.maxMessageSize];
} else {
return channel;
}
});
}
_.merge(runtime, config.relaychain.runtimeGenesisConfig);
}
// genesis parachains
for (const parachain of config.parachains) {
const { wasm, state } = exportParachainGenesis(parachain, output);
if (!parachain.id) {
return fatal('Missing parachains[].id');
}
const para = [
parachain.id,
{
genesis_head: state,
validation_code: wasm,
parachain: parachain.parachain,
},
];
runtime.paras.paras.push(para);
}
const tmpfile = `${shell.tempdir()}/${config.relaychain.chain}.json`;
fs.writeFileSync(tmpfile, jsonStringify(spec));
exec(
`docker run --rm -v "${tmpfile}":/${config.relaychain.chain}.json ${config.relaychain.image} build-spec --raw --chain=/${config.relaychain.chain}.json --disable-default-bootnode > ${path}`
);
shell.rm(tmpfile);
console.log('Relaychain genesis generated at', path);
}
Example #24
Source File: skip-bug-ethereum-parent-hash.ts From moonbeam with GNU General Public License v3.0 | 4 votes |
describeParachain(
`Runtime ${runtimeVersion} migration`,
{
parachain: {
chain: "moonbase-local",
runtime: "runtime-1103",
binary: "v0.19.1",
},
relaychain: {
binary: "v0.9.13",
},
},
(context) => {
it("have proper parent hash", async function () {
// Expected to take 4 blocks to setup + 10 blocks for upgrade + 4 blocks to check =>
// ~300000 + init 50000 + error marging 150000
this.timeout(500000);
const keyring = new Keyring({ type: "ethereum" });
const alith = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
const baltathar = await keyring.addFromUri(BALTATHAR_PRIV_KEY, null, "ethereum");
let baltatharNonce = await context.web3.eth.getTransactionCount(baltathar.address);
// It takes 10 blocks
let hasMoreBlockPassed = false;
const runtimePromise = context
.upgradeRuntime(alith, "moonbase", runtimeVersion)
.then(async (blockNumber) => {
context.waitBlocks(3).then(() => {
hasMoreBlockPassed = true;
});
return blockNumber;
});
// It takes 5 blocks for the runtime, however we need to send before to have
// the extrinsics included
while (!hasMoreBlockPassed) {
const tx = await context.web3.eth.accounts.signTransaction(
{
from: baltathar.address,
to: alith.address,
value: Web3.utils.toWei("1", "ether"),
gasPrice: Web3.utils.toWei("1", "Gwei"),
gas: "0x100000",
nonce: baltatharNonce++,
},
BALTATHAR_PRIV_KEY
);
await customWeb3Request(context.web3, "eth_sendRawTransaction", [tx.rawTransaction]);
await new Promise((resolve) => setTimeout(resolve, 12000));
}
for (let i = 1; i < context.blockNumber - 1; i++) {
console.log(
`#${i} ${(await context.web3.eth.getBlock(i)).parentHash} ${
(
await context.polkadotApiParaone.rpc.state.getRuntimeVersion(
await context.polkadotApiParaone.rpc.chain.getBlockHash(i)
)
).specVersion
} (${
(
await context.polkadotApiParaone.rpc.chain.getBlock(
await context.polkadotApiParaone.rpc.chain.getBlockHash(i)
)
).block.extrinsics.length
} ext)`
);
}
process.stdout.write(`!!!!! \n`);
expect((await context.web3.eth.getBlock((await runtimePromise) + 1)).parentHash).to.be.string(
"0x0000000000000000000000000000000000000000000000000000000000000000"
); // new runtime only allow 50 bottom
process.stdout.write(`✅\n`);
process.stdout.write("Waiting extra block being produced...");
await context.waitBlocks(2); // Make sure the new runtime is producing blocks
process.stdout.write(`✅ total ${context.blockNumber} block produced\n`);
});
}
);
Example #25
Source File: vaults.test.ts From interbtc-api with Apache License 2.0 | 4 votes |
describe("vaultsAPI", () => {
let oracleAccount: KeyringPair;
let vault_to_liquidate: KeyringPair;
let vault_to_ban: KeyringPair;
let vault_1: KeyringPair;
let vault_1_id: InterbtcPrimitivesVaultId;
let vault_2: KeyringPair;
let vault_2_id: InterbtcPrimitivesVaultId;
let vault_3: KeyringPair;
let vault_3_id: InterbtcPrimitivesVaultId;
let api: ApiPromise;
let bitcoinCoreClient: BitcoinCoreClient;
let wrappedCurrency: WrappedCurrency;
let collateralCurrency: CollateralCurrency;
let governanceCurrency: Currency<GovernanceUnit>;
let interBtcAPI: InterBtcApi;
let oracleInterBtcAPI: InterBtcApi;
before(async () => {
api = await createSubstrateAPI(PARACHAIN_ENDPOINT);
const keyring = new Keyring({ type: "sr25519" });
oracleAccount = keyring.addFromUri(ORACLE_URI);
interBtcAPI = new DefaultInterBtcApi(api, "regtest", undefined, ESPLORA_BASE_PATH);
oracleInterBtcAPI = new DefaultInterBtcApi(api, "regtest", oracleAccount, ESPLORA_BASE_PATH);
wrappedCurrency = interBtcAPI.getWrappedCurrency();
governanceCurrency = interBtcAPI.getGovernanceCurrency();
collateralCurrency = getCorrespondingCollateralCurrency(governanceCurrency);
vault_1 = keyring.addFromUri(VAULT_1_URI);
vault_1_id = newVaultId(api, vault_1.address, collateralCurrency, wrappedCurrency);
vault_2 = keyring.addFromUri(VAULT_2_URI);
vault_2_id = newVaultId(api, vault_2.address, collateralCurrency, wrappedCurrency);
vault_3 = keyring.addFromUri(VAULT_3_URI);
vault_3_id = newVaultId(api, vault_3.address, collateralCurrency, wrappedCurrency);
vault_to_ban = keyring.addFromUri(VAULT_TO_BAN_URI);
vault_to_liquidate = keyring.addFromUri(VAULT_TO_LIQUIDATE_URI);
bitcoinCoreClient = new BitcoinCoreClient(
BITCOIN_CORE_NETWORK,
BITCOIN_CORE_HOST,
BITCOIN_CORE_USERNAME,
BITCOIN_CORE_PASSWORD,
BITCOIN_CORE_PORT,
BITCOIN_CORE_WALLET
);
});
after(() => {
return api.disconnect();
});
afterEach(() => {
// discard any stubbed methods after each test
sinon.restore();
});
function vaultIsATestVault(vaultAddress: string): boolean {
return vaultAddress === vault_2.address ||
vaultAddress === vault_1.address ||
vaultAddress === vault_3.address ||
vaultAddress === vault_to_ban.address ||
vaultAddress === vault_to_liquidate.address;
}
// FIXME: this should be tested in a way that in doesn't use magic numbers
it("should get issuable", async () => {
const issuableInterBTC = await interBtcAPI.vaults.getTotalIssuableAmount();
const minExpectedIssuableInterBTC = newMonetaryAmount(0.002, wrappedCurrency, true);
assert.isTrue(issuableInterBTC.gte(minExpectedIssuableInterBTC), `Issuable ${issuableInterBTC.toHuman()}`);
});
it("should get the required collateral for the vault", async () => {
const collateralCurrency = currencyIdToMonetaryCurrency(vault_1_id.currencies.collateral) as Currency<CollateralUnit>;
const requiredCollateralForVault =
await interBtcAPI.vaults.getRequiredCollateralForVault(vault_1_id.accountId, collateralCurrency);
const vault = await interBtcAPI.vaults.get(vault_1_id.accountId, currencyIdToLiteral(vault_1_id.currencies.collateral));
// The numeric value of the required collateral should be greater than that of issued tokens.
// e.g. we require `0.8096` KSM for `0.00014` kBTC
assert.isTrue(requiredCollateralForVault.toBig().gt(vault.getBackedTokens().toBig()));
});
// WARNING: this test is not idempotent
it("should deposit and withdraw collateral", async () => {
const prevAccount = interBtcAPI.account;
interBtcAPI.setAccount(vault_1);
const amount = newMonetaryAmount(100, collateralCurrency as Currency<CollateralUnit>, true);
const collateralCurrencyIdLiteral = tickerToCurrencyIdLiteral(collateralCurrency.ticker) as CollateralIdLiteral;
const collateralizationBeforeDeposit =
await interBtcAPI.vaults.getVaultCollateralization(newAccountId(api, vault_1.address), collateralCurrencyIdLiteral);
await interBtcAPI.vaults.depositCollateral(amount);
const collateralizationAfterDeposit =
await interBtcAPI.vaults.getVaultCollateralization(newAccountId(api, vault_1.address), collateralCurrencyIdLiteral);
if (collateralizationBeforeDeposit === undefined || collateralizationAfterDeposit == undefined) {
throw new Error("Collateralization is undefined");
}
assert.isTrue(
collateralizationAfterDeposit.gt(collateralizationBeforeDeposit),
`Depositing did not increase collateralization,
expected ${collateralizationAfterDeposit} greater than ${collateralizationBeforeDeposit}`
);
await interBtcAPI.vaults.withdrawCollateral(amount);
const collateralizationAfterWithdrawal =
await interBtcAPI.vaults.getVaultCollateralization(newAccountId(api, vault_1.address), collateralCurrencyIdLiteral);
if (collateralizationAfterWithdrawal === undefined) {
throw new Error("Collateralization is undefined");
}
assert.isTrue(
collateralizationAfterDeposit.gt(collateralizationAfterWithdrawal),
`Withdrawing did not decrease collateralization, expected
${collateralizationAfterDeposit} greater than ${collateralizationAfterWithdrawal}`
);
assert.equal(
collateralizationBeforeDeposit.toString(), collateralizationAfterWithdrawal.toString(),
"Collateralization after identical deposit and withdrawal changed"
);
if (prevAccount) {
interBtcAPI.setAccount(prevAccount);
}
});
it("should getPremiumRedeemVaults after a price crash", async () => {
const collateralCurrencyIdLiteral = currencyIdToLiteral(vault_3_id.currencies.collateral) as CollateralIdLiteral;
const vault = await interBtcAPI.vaults.get(vault_3_id.accountId, collateralCurrencyIdLiteral);
let issuableAmount = await vault.getIssuableTokens();
// TODO: Look into why requesting the full issuable amount fails, and remove the line below
issuableAmount = issuableAmount.mul(0.9);
await issueSingle(interBtcAPI, bitcoinCoreClient, oracleAccount, issuableAmount, vault_3_id);
const currentVaultCollateralization =
await interBtcAPI.vaults.getVaultCollateralization(newAccountId(api, vault_3.address), collateralCurrencyIdLiteral);
if (currentVaultCollateralization === undefined) {
throw new Error("Collateralization is undefined");
}
const collateralCurrencyTyped = collateralCurrency as Currency<CollateralUnit>;
// The factor to adjust the exchange rate by. Calculated such that the resulting collateralization
// will be 90% of the premium redeem threshold. (e.g. 1.35 * 90% = 1.215)
const premiumRedeemThreshold = await interBtcAPI.vaults.getPremiumRedeemThreshold(collateralCurrency);
const modifyExchangeRateBy = premiumRedeemThreshold.mul(0.9).div(currentVaultCollateralization);
const initialExchangeRate = await interBtcAPI.oracle.getExchangeRate(collateralCurrencyTyped);
// crash the exchange rate so that the vault falls below the premium redeem threshold
const exchangeRateValue = initialExchangeRate.toBig().div(modifyExchangeRateBy);
const mockExchangeRate = new ExchangeRate<
Bitcoin,
BitcoinUnit,
typeof collateralCurrencyTyped,
typeof collateralCurrencyTyped.units
>(Bitcoin, collateralCurrencyTyped, exchangeRateValue);
// stub the oracle API to always return the new exchange rate
const stub = sinon.stub(interBtcAPI.oracle, "getExchangeRate")
.withArgs(sinon.match.any)
.returns(Promise.resolve(mockExchangeRate as any)); // "as any" to help eslint play nicely
const premiumRedeemVaults = await interBtcAPI.vaults.getPremiumRedeemVaults();
// Check that the stub has indeed been called at least once
// If not, code has changed and our assumptions when mocking the oracle API are no longer valid
sinon.assert.called(stub);
// real assertions here
assert.equal(premiumRedeemVaults.size, 1);
assert.equal(
encodeVaultId(premiumRedeemVaults.keys().next().value),
encodeVaultId(vault_3_id),
"Premium redeem vault is not the expected one"
);
const premiumRedeemAmount = premiumRedeemVaults.values().next().value;
assert.isTrue(
premiumRedeemAmount.gte(issuableAmount),
"Amount available for premium redeem should be higher"
);
}).timeout(5 * 60000);
it("should getLiquidationCollateralThreshold", async () => {
const threshold = await interBtcAPI.vaults.getLiquidationCollateralThreshold(collateralCurrency);
assert.equal(threshold.toString(), "1.1");
});
it("should getPremiumRedeemThreshold", async () => {
const threshold = await interBtcAPI.vaults.getPremiumRedeemThreshold(collateralCurrency);
assert.equal(threshold.toString(), "1.35");
});
it("should select random vault for issue", async () => {
const randomVault = await interBtcAPI.vaults.selectRandomVaultIssue(newMonetaryAmount(0, wrappedCurrency));
assert.isTrue(vaultIsATestVault(randomVault.accountId.toHuman()));
});
it("should fail if no vault for issuing is found", async () => {
assert.isRejected(interBtcAPI.vaults.selectRandomVaultIssue(newMonetaryAmount(9000000, wrappedCurrency, true)));
});
it("should select random vault for redeem", async () => {
const randomVault = await interBtcAPI.vaults.selectRandomVaultRedeem(newMonetaryAmount(0, wrappedCurrency));
assert.isTrue(vaultIsATestVault(randomVault.accountId.toHuman()));
});
it("should fail if no vault for redeeming is found", async () => {
const amount = newMonetaryAmount(9000000, wrappedCurrency, true);
assert.isRejected(interBtcAPI.vaults.selectRandomVaultRedeem(amount));
});
it("should fail to get vault collateralization for vault with zero collateral", async () => {
const vault1Id = newAccountId(api, vault_1.address);
const collateralCurrencyIdLiteral = tickerToCurrencyIdLiteral(collateralCurrency.ticker) as CollateralIdLiteral;
assert.isRejected(interBtcAPI.vaults.getVaultCollateralization(vault1Id, collateralCurrencyIdLiteral));
});
it("should get the issuable InterBtc for a vault", async () => {
const collateralCurrencyIdLiteral = currencyIdToLiteral(vault_1_id.currencies.collateral) as CollateralIdLiteral;
const vault = await interBtcAPI.vaults.get(vault_1_id.accountId, collateralCurrencyIdLiteral);
const issuableTokens = await vault.getIssuableTokens();
assert.isTrue(issuableTokens.gt(newMonetaryAmount(0, wrappedCurrency)));
});
it("should get the issuable InterBtc", async () => {
const issuableInterBtc = await interBtcAPI.vaults.getTotalIssuableAmount();
assert.isTrue(issuableInterBtc.gt(newMonetaryAmount(0, wrappedCurrency)));
});
// TODO: revisit after next publish why intrReward is always zero
it.skip("should getFees", async () => {
const vault1Id = newAccountId(api, vault_1.address);
const feesWrapped = await interBtcAPI.vaults.getWrappedReward(
vault1Id,
currencyIdToLiteral(vault_1_id.currencies.collateral) as CollateralIdLiteral,
currencyIdToLiteral(vault_1_id.currencies.wrapped) as WrappedIdLiteral
);
assert.isTrue(feesWrapped.gt(newMonetaryAmount(0, wrappedCurrency)));
const intrReward = await interBtcAPI.vaults.getGovernanceReward(
vault1Id,
currencyIdToLiteral(vault_1_id.currencies.collateral) as CollateralIdLiteral,
tickerToCurrencyIdLiteral(governanceCurrency.ticker) as GovernanceIdLiteral
);
assert.isTrue(feesWrapped.gt(newMonetaryAmount(0, wrappedCurrency)));
assert.isTrue(intrReward.gt(newMonetaryAmount(0, governanceCurrency)));
});
it("should getAPY", async () => {
const apy =
await interBtcAPI.vaults.getAPY(
newAccountId(api, vault_1.address), currencyIdToLiteral(vault_1_id.currencies.collateral) as CollateralIdLiteral
);
const apyBig = new Big(apy);
const apyBenchmark = new Big("0");
assert.isTrue(apyBig.gte(apyBenchmark));
});
it("should getPunishmentFee", async () => {
const punishmentFee = await interBtcAPI.vaults.getPunishmentFee();
assert.equal(punishmentFee.toString(), "0.1");
});
it("should get vault list", async () => {
const vaults = (await interBtcAPI.vaults.list()).map(vault => vault.id.toHuman());
assert.isAbove(vaults.length, 0, "Vault list should not be empty");
});
it("should disable and enable issuing with vault", async () => {
const assertVaultStatus = async (id: InterbtcPrimitivesVaultId, expectedStatus: VaultStatusExt) => {
const collateralCurrencyIdLiteral = currencyIdToLiteral(id.currencies.collateral);
const { status } = await interBtcAPI.vaults.get(id.accountId, collateralCurrencyIdLiteral);
const assertionMessage = `Vault with id ${id.toString()} was expected to have
status: ${vaultStatusToLabel(expectedStatus)}, but got status: ${vaultStatusToLabel(status)}`;
assert.isTrue(status === expectedStatus, assertionMessage);
};
const ACCEPT_NEW_ISSUES = true;
const REJECT_NEW_ISSUES = false;
// Check that vault 1 is active.
await assertVaultStatus(vault_1_id, VaultStatusExt.Active);
// Disables vault 1 which is active.
await interBtcAPI.vaults.toggleIssueRequests(vault_1_id, REJECT_NEW_ISSUES);
// Check that vault 1 is inactive.
await assertVaultStatus(vault_1_id, VaultStatusExt.Inactive);
// Re-enable issuing with vault 1.
await interBtcAPI.vaults.toggleIssueRequests(vault_1_id, ACCEPT_NEW_ISSUES);
// Check that vault 1 is again active.
await assertVaultStatus(vault_1_id, VaultStatusExt.Active);
});
});
Example #26
Source File: test-staking.ts From moonbeam with GNU General Public License v3.0 | 4 votes |
async function test() {
await start("config_moonbeam_staking.json");
const WS_PORT = 36946;
const wsProviderUrl = `ws://localhost:${WS_PORT}`;
const wsProvider = new WsProvider(wsProviderUrl);
const polkadotApi = await ApiPromise.create({
provider: wsProvider,
typesBundle: typesBundlePre900 as any,
});
// subscribe to all new headers (with extended info)
let lastBlock = Date.now();
polkadotApi.derive.chain.subscribeNewHeads((header) => {
console.log(
`New Block: #${header.number}: ${header.author}, time since last block: ${
(Date.now() - lastBlock) / 1000
} sec`
);
lastBlock = Date.now();
});
// Balance
const account = await polkadotApi.query.system.account(ETHAN);
assert(
account.data.free.toString() === DEFAULT_GENESIS_BALANCE.toString(),
"wrong balance for Ethan, dif: " + (Number(DEFAULT_GENESIS_BALANCE) - Number(account.data.free))
);
// Nominators
const nominators = await polkadotApi.query.parachainStaking.nominatorState(GERALD);
assert(nominators.toHuman() === null, "there should be no nominator");
// Validators
const validators = await polkadotApi.query.parachainStaking.selectedCandidates();
assert(validators.toHuman()[0] === GERALD, "Gerald is not a validator");
assert(validators.toHuman()[1] === FAITH, "Faith is not a validator");
// Candidates
const candidates = await polkadotApi.query.parachainStaking.candidatePool();
assert(candidates.toHuman()[0].owner === GERALD, "Gerald is not a candidates");
assert(candidates.toHuman()[1].owner === FAITH, "Faith is not a candidates");
assert(candidates.toHuman()[0].amount === STAKING_AMOUNT, "Gerald has wrong staking amount");
assert(candidates.toHuman()[1].amount === STAKING_AMOUNT, "Faith has wrong staking amount");
// Join Candidates
const keyring = new Keyring({ type: "ethereum" });
const ethan = await keyring.addFromUri(ETHAN_PRIVKEY, null, "ethereum");
await new Promise<void>(async (res) => {
const unsub = await polkadotApi.tx.parachainStaking
.joinCandidates(MIN_GLMR_STAKING)
.signAndSend(ethan, ({ events = [], status }) => {
console.log(`Current status is ${status.type}`);
if (status.isInBlock) {
console.log(`Transaction included in Block at blockHash ${status.asInBlock}`);
// Loopcod through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
} else if (status.isFinalized) {
console.log(`Transaction finalized at blockHash ${status.asFinalized}`);
// Loopcod through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
}
});
});
let candidatesAfter = await polkadotApi.query.parachainStaking.candidatePool();
assert(
(candidatesAfter.toHuman() as { owner: string; amount: string }[]).length === 3,
"new candidate should have been added"
);
assert(
(candidatesAfter.toHuman() as { owner: string; amount: string }[])[2].owner === ETHAN,
"new candidate ethan should have been added"
);
assert(
(candidatesAfter.toHuman() as { owner: string; amount: string }[])[2].amount === "1.0000 kUnit",
"new candidate ethan should have been added (wrong amount)"
);
// Candidate bond more
await new Promise<void>(async (res) => {
const unsub = await polkadotApi.tx.parachainStaking
.candidateBondMore(MIN_GLMR_STAKING)
.signAndSend(ethan, ({ events = [], status }) => {
console.log(`Current status is ${status.type}`);
if (status.isInBlock) {
console.log(`Transaction included in Block at blockHash ${status.asInBlock}`);
// Loopcod through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
} else if (status.isFinalized) {
console.log(`Transaction finalized at blockHash ${status.asFinalized}`);
// Loopcod through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
}
});
});
candidatesAfter = await polkadotApi.query.parachainStaking.candidatePool();
assert(
(candidatesAfter.toHuman() as { owner: string; amount: string }[])[2].amount === "2.0000 kUnit",
"bond should have increased"
);
// Candidate bond less
await new Promise<void>(async (res) => {
const unsub = await polkadotApi.tx.parachainStaking
.candidateBondLess(MIN_GLMR_STAKING)
.signAndSend(ethan, ({ events = [], status }) => {
console.log(`Current status is ${status.type}`);
if (status.isInBlock) {
console.log(`Transaction included in Block at blockHash ${status.asInBlock}`);
// Loopcod through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
} else if (status.isFinalized) {
console.log(`Transaction finalized at blockHash ${status.asFinalized}`);
// Loopcod through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
}
});
});
candidatesAfter = await polkadotApi.query.parachainStaking.candidatePool();
assert(
(candidatesAfter.toHuman() as { owner: string; amount: string }[])[2].amount === "1.0000 kUnit",
"bond should have decreased"
);
// Join Nominators
const keyringAlith = new Keyring({ type: "ethereum" });
const alith = await keyringAlith.addFromUri(ALITH_PRIVKEY, null, "ethereum");
await new Promise<void>(async (res) => {
const unsub = await polkadotApi.tx.parachainStaking
.nominate(GERALD, MIN_GLMR_NOMINATOR)
.signAndSend(alith, ({ events = [], status }) => {
console.log(`Current status is ${status.type}`);
if (status.isInBlock) {
console.log(`Transaction included in Block at blockHash ${status.asInBlock}`);
// Loopcod through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
} else if (status.isFinalized) {
console.log(`Transaction finalized at blockHash ${status.asFinalized}`);
// Loop through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
}
});
});
const nominatorsAfter = await polkadotApi.query.parachainStaking.nominatorState(ALITH);
assert(
(
nominatorsAfter.toHuman() as {
nominations: { owner: string; amount: string }[];
}
).nominations[0].owner === GERALD,
"nomination didnt go through"
);
// Revoke Delegation
await new Promise<void>(async (res) => {
const unsub = await polkadotApi.tx.parachainStaking
.revokeDelegation(GERALD) //TODO: when converting to test add .leaveNominators()
// that should produce the same behavior
.signAndSend(alith, ({ events = [], status }) => {
console.log(`Current status is ${status.type}`);
if (status.isInBlock) {
console.log(`Transaction included in Block at blockHash ${status.asInBlock}`);
// Loopcod through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
} else if (status.isFinalized) {
console.log(`Transaction finalized at blockHash ${status.asFinalized}`);
// Loop through Vec<EventRecord> to display all events
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(`\t' ${phase}: ${section}.${method}:: ${data}`);
});
unsub();
res();
}
});
});
const nominatorsAfterRevocation = await polkadotApi.query.parachainStaking.nominatorState(ALITH);
assert(nominatorsAfterRevocation.toHuman() === null, "there should be no nominator");
console.log("SUCCESS");
}
Example #27
Source File: redeem.test.ts From interbtc-api with Apache License 2.0 | 4 votes |
describe("redeem", () => {
let api: ApiPromise;
let keyring: Keyring;
let userAccount: KeyringPair;
const randomBtcAddress = "bcrt1qujs29q4gkyn2uj6y570xl460p4y43ruayxu8ry";
let bitcoinCoreClient: BitcoinCoreClient;
let vault_1: KeyringPair;
let vault_1_id: InterbtcPrimitivesVaultId;
let vault_2: KeyringPair;
let vault_2_id: InterbtcPrimitivesVaultId;
let wrappedCurrency: WrappedCurrency;
let collateralCurrency: CollateralCurrency;
let interBtcAPI: InterBtcApi;
before(async () => {
api = await createSubstrateAPI(PARACHAIN_ENDPOINT);
keyring = new Keyring({ type: "sr25519" });
userAccount = keyring.addFromUri(USER_1_URI);
interBtcAPI = new DefaultInterBtcApi(api, "regtest", userAccount, ESPLORA_BASE_PATH);
collateralCurrency = getCorrespondingCollateralCurrency(interBtcAPI.getGovernanceCurrency());
wrappedCurrency = interBtcAPI.getWrappedCurrency();
vault_1 = keyring.addFromUri(VAULT_1_URI);
vault_1_id = newVaultId(api, vault_1.address, collateralCurrency, wrappedCurrency);
vault_2 = keyring.addFromUri(VAULT_2_URI);
vault_2_id = newVaultId(api, vault_2.address, collateralCurrency, wrappedCurrency);
bitcoinCoreClient = new BitcoinCoreClient(
BITCOIN_CORE_NETWORK,
BITCOIN_CORE_HOST,
BITCOIN_CORE_USERNAME,
BITCOIN_CORE_PASSWORD,
BITCOIN_CORE_PORT,
BITCOIN_CORE_WALLET
);
});
after(() => {
return api.disconnect();
});
it("should fail if no account is set", async () => {
const amount = newMonetaryAmount(10, wrappedCurrency);
await assert.isRejected(interBtcAPI.redeem.request(amount, randomBtcAddress));
}).timeout(3 * 60000);
it("should issue and request redeem", async () => {
const issueAmount = newMonetaryAmount(0.00005, wrappedCurrency, true);
const redeemAmount = newMonetaryAmount(0.00003, wrappedCurrency, true);
await issueAndRedeem(
interBtcAPI,
bitcoinCoreClient,
userAccount,
vault_1_id,
issueAmount,
redeemAmount,
false,
ExecuteRedeem.False
);
await issueAndRedeem(
interBtcAPI,
bitcoinCoreClient,
userAccount,
vault_2_id,
issueAmount,
redeemAmount,
false,
ExecuteRedeem.False
);
}).timeout(8 * 60000);
it("should load existing redeem requests", async () => {
const redeemRequests = await interBtcAPI.redeem.list();
assert.isAtLeast(
redeemRequests.length,
1,
"Error in initialization setup. Should have at least 1 issue request"
);
});
// TODO: maybe add this to redeem API
it("should get redeemBtcDustValue", async () => {
const dust = await interBtcAPI.api.query.redeem.redeemBtcDustValue();
assert.equal(dust.toString(), "1000");
});
it("should getFeesToPay", async () => {
const amount = newMonetaryAmount(2, wrappedCurrency, true);
const feesToPay = await interBtcAPI.redeem.getFeesToPay(amount);
assert.equal(feesToPay.str.BTC(), "0.01");
});
it("should getFeeRate", async () => {
const feePercentage = await interBtcAPI.redeem.getFeeRate();
assert.equal(feePercentage.toString(), "0.005");
});
it("should getPremiumRedeemFeeRate", async () => {
const premiumRedeemFee = await interBtcAPI.redeem.getPremiumRedeemFeeRate();
assert.equal(premiumRedeemFee.toString(), "0.05");
});
it("should getCurrentInclusionFee", async () => {
const currentInclusionFee = await interBtcAPI.redeem.getCurrentInclusionFee();
assert.isTrue(!currentInclusionFee.isZero());
});
it("should getDustValue", async () => {
const dustValue = await interBtcAPI.redeem.getDustValue();
assert.equal(dustValue.str.BTC(), "0.00001");
});
});
Example #28
Source File: test-precompile-democracy.ts From moonbeam with GNU General Public License v3.0 | 4 votes |
describeDevMoonbeam("Democracy - second proposal", (context) => {
let genesisAccount: KeyringPair, alith: KeyringPair;
let encodedHash: `0x${string}`;
let launchPeriod;
let iFace: Interface;
before("Setup genesis account for substrate", async () => {
const keyring = new Keyring({ type: "ethereum" });
genesisAccount = await keyring.addFromUri(GENESIS_ACCOUNT_PRIVATE_KEY, null, "ethereum");
alith = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
iFace = await deployAndInterfaceContract(context, "Democracy");
//launchPeriod
launchPeriod = await context.polkadotApi.consts.democracy.launchPeriod;
// notePreimage
encodedHash = await notePreimagePrecompile(
context,
iFace,
context.polkadotApi.tx.parachainStaking.setParachainBondAccount(GENESIS_ACCOUNT)
);
// propose
await sendPrecompileTx(
context,
ADDRESS_DEMO_PRECOMPILE,
SELECTORS,
GENESIS_ACCOUNT,
GENESIS_ACCOUNT_PRIVATE_KEY,
"propose",
[encodedHash, numberToHex(Number(PROPOSAL_AMOUNT))]
);
// second
await sendPrecompileTx(
context,
ADDRESS_DEMO_PRECOMPILE,
SELECTORS,
ALITH,
ALITH_PRIV_KEY,
"second",
[numberToHex(0), numberToHex(1000)]
);
});
// TODO: test getters
it("second proposal", async function () {
// publicProps
const publicProps = await context.polkadotApi.query.democracy.publicProps();
// encodedHash
expect((publicProps.toHuman() as any)[0][1]).to.equal(encodedHash);
// prop author
expect((publicProps.toHuman() as any)[0][2]).to.equal(GENESIS_ACCOUNT);
// depositOf
const depositOf = await context.polkadotApi.query.democracy.depositOf(0);
expect((depositOf.toHuman() as any)[1]).to.equal("1,000,000,000,000,000,000,000");
expect((depositOf.toHuman() as any)[0][1]).to.equal(ALITH);
});
it("check launch period", async function () {
// launchPeriod
expect(launchPeriod.toHuman()).to.equal("7,200");
});
it("check referendum is up", async function () {
this.timeout(1000000);
// let Launchperiod elapse to turn the proposal into a referendum
// launchPeriod minus the 3 blocks that already elapsed
for (let i = 0; i < Number(launchPeriod) - 3; i++) {
await context.createBlock();
}
// referendumCount
let referendumCount = await context.polkadotApi.query.democracy.referendumCount();
expect(referendumCount.toHuman()).to.equal("1");
// publicPropCount
const publicPropCount = await context.polkadotApi.query.democracy.publicPropCount();
expect(publicPropCount.toHuman()).to.equal("1");
// referendumInfoOf
const referendumInfoOf = await context.polkadotApi.query.democracy.referendumInfoOf(0);
expect((referendumInfoOf.toHuman() as any).Ongoing.proposalHash).to.equal(encodedHash);
});
});
Example #29
Source File: nomination.test.ts From interbtc-api with Apache License 2.0 | 4 votes |
// TODO: readd this once we want to activate nomination
describe.skip("NominationAPI", () => {
let api: ApiPromise;
let userInterBtcAPI: InterBtcApi;
let sudoInterBtcAPI: InterBtcApi;
let sudoAccount: KeyringPair;
let userAccount: KeyringPair;
let vault_1: KeyringPair;
let vault_1_id: InterbtcPrimitivesVaultId;
let bitcoinCoreClient: BitcoinCoreClient;
let wrappedCurrency: WrappedCurrency;
let collateralCurrency: CollateralCurrency;
before(async () => {
api = await createSubstrateAPI(PARACHAIN_ENDPOINT);
const keyring = new Keyring({ type: "sr25519" });
sudoAccount = keyring.addFromUri(SUDO_URI);
userAccount = keyring.addFromUri(USER_1_URI);
// TODO: remove all uses of config currencies and query the chain instead
userInterBtcAPI = new DefaultInterBtcApi(api, "regtest", userAccount, ESPLORA_BASE_PATH);
sudoInterBtcAPI = new DefaultInterBtcApi(api, "regtest", sudoAccount, ESPLORA_BASE_PATH);
collateralCurrency = getCorrespondingCollateralCurrency(userInterBtcAPI.getGovernanceCurrency());
wrappedCurrency = userInterBtcAPI.getWrappedCurrency();
vault_1 = keyring.addFromUri(VAULT_1_URI);
vault_1_id = newVaultId(api, vault_1.address, collateralCurrency, wrappedCurrency);
if (!(await sudoInterBtcAPI.nomination.isNominationEnabled())) {
console.log("Enabling nomination...");
await sudo(sudoInterBtcAPI, () => sudoInterBtcAPI.nomination.setNominationEnabled(true));
}
// The account of a vault from docker-compose
vault_1 = keyring.addFromUri(VAULT_1_URI);
bitcoinCoreClient = new BitcoinCoreClient(
BITCOIN_CORE_NETWORK,
BITCOIN_CORE_HOST,
BITCOIN_CORE_USERNAME,
BITCOIN_CORE_PASSWORD,
BITCOIN_CORE_PORT,
BITCOIN_CORE_WALLET
);
});
after(() => {
return api.disconnect();
});
it("Should opt a vault in and out of nomination", async () => {
await optInWithAccount(vault_1, currencyIdToMonetaryCurrency(vault_1_id.currencies.collateral) as CollateralCurrency);
const nominationVaults = await userInterBtcAPI.nomination.listVaults();
assert.equal(1, nominationVaults.length);
assert.equal(vault_1.address, nominationVaults.map(v => v.accountId.toString())[0]);
await optOutWithAccount(vault_1, currencyIdToMonetaryCurrency(vault_1_id.currencies.collateral) as CollateralCurrency);
assert.equal(0, (await userInterBtcAPI.nomination.listVaults()).length);
}).timeout(60000);
async function setIssueFee(x: BN) {
await setNumericStorage(api, "Fee", "IssueFee", x, sudoAccount, 128);
}
it("Should nominate to and withdraw from a vault", async () => {
await optInWithAccount(vault_1, currencyIdToMonetaryCurrency(vault_1_id.currencies.collateral) as CollateralCurrency);
const issueFee = await userInterBtcAPI.fee.getIssueFee();
const collateralCurrencyIdLiteral = currencyIdToLiteral(vault_1_id.currencies.collateral) as CollateralIdLiteral;
const vault = await userInterBtcAPI.vaults.get(vault_1_id.accountId, collateralCurrencyIdLiteral);
const collateralCurrency = currencyIdToMonetaryCurrency(vault.id.currencies.collateral) as Currency<CollateralUnit>;
const nominatorDeposit = newMonetaryAmount(1, collateralCurrency, true);
try {
// Set issue fees to 100%
await setIssueFee(new BN("1000000000000000000"));
const stakingCapacityBeforeNomination = await userInterBtcAPI.vaults.getStakingCapacity(
vault_1_id.accountId,
collateralCurrencyIdLiteral
);
// Deposit
await userInterBtcAPI.nomination.depositCollateral(vault_1_id.accountId, nominatorDeposit);
const stakingCapacityAfterNomination = await userInterBtcAPI.vaults.getStakingCapacity(
vault_1_id.accountId,
collateralCurrencyIdLiteral
);
assert.equal(
stakingCapacityBeforeNomination.sub(nominatorDeposit).toString(),
stakingCapacityAfterNomination.toString(),
"Nomination failed to decrease staking capacity"
);
const nominationPairs = await userInterBtcAPI.nomination.list();
assert.equal(2, nominationPairs.length, "There should be one nomination pair in the system, besides the vault to itself");
const userAddress = userAccount.address;
const vault_1Address = vault_1.address;
const nomination = nominationPairs.find((nomination) => userAddress == nomination.nominatorId.toString()) as Nomination;
assert.equal(userAddress, nomination.nominatorId.toString());
assert.equal(vault_1Address, nomination.vaultId.accountId.toString());
const amountToIssue = newMonetaryAmount(0.00001, wrappedCurrency, true);
await issueSingle(userInterBtcAPI, bitcoinCoreClient, userAccount, amountToIssue, vault_1_id);
const wrappedRewardsBeforeWithdrawal = (
await userInterBtcAPI.nomination.getNominatorReward(
vault_1_id.accountId,
collateralCurrencyIdLiteral,
tickerToCurrencyIdLiteral(wrappedCurrency.ticker),
newAccountId(api, userAccount.address),
)
).toBig();
assert.isTrue(
wrappedRewardsBeforeWithdrawal.gt(0),
"Nominator should receive non-zero wrapped tokens"
);
// Withdraw Rewards
await userInterBtcAPI.rewards.withdrawRewards(vault_1_id);
// Withdraw Collateral
await userInterBtcAPI.nomination.withdrawCollateral(vault_1_id.accountId, nominatorDeposit);
const nominatorsAfterWithdrawal = await userInterBtcAPI.nomination.list();
// The vault always has a "nomination" to itself
assert.equal(1, nominatorsAfterWithdrawal.length);
const totalNomination = await userInterBtcAPI.nomination.getTotalNomination(
newAccountId(api, userAccount.address),
currencyIdToMonetaryCurrency(vault_1_id.currencies.collateral) as CollateralCurrency,
);
assert.equal(totalNomination.toString(), "0");
} catch(error) {
throw error;
} finally {
await setIssueFee(encodeUnsignedFixedPoint(api, issueFee));
await optOutWithAccount(vault_1, currencyIdToMonetaryCurrency(vault_1_id.currencies.collateral) as CollateralCurrency);
}
}).timeout(5 * 60000);
async function optInWithAccount(vaultAccount: KeyringPair, collateralCurrency: CollateralCurrency) {
// will fail if vault is already opted in
await callWith(userInterBtcAPI, vaultAccount, () => userInterBtcAPI.nomination.optIn(collateralCurrency));
}
async function optOutWithAccount(vaultAccount: KeyringPair, collateralCurrency: CollateralCurrency) {
await callWith(userInterBtcAPI, vaultAccount, () => userInterBtcAPI.nomination.optOut(collateralCurrency));
}
});