-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
530 additions
and
243 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
endpoint: wss://basilisk-rococo-rpc.play.hydration.cloud | ||
mock-signature-host: true | ||
block: ${env.BASILISK_BLOCK_NUMBER} | ||
db: ./tmp/basilisk_db_mba.sqlite | ||
|
||
import-storage: | ||
System: | ||
Account: | ||
- | ||
- | ||
- 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY | ||
- providers: 1 | ||
data: | ||
free: 1000000000000000 | ||
Tokens: | ||
Accounts: | ||
- | ||
- | ||
- 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY | ||
- 17 | ||
- free: '100000000000000000000' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
// Copyright (C) Moondance Labs Ltd. | ||
|
||
import { expect, ChopsticksContext } from "@moonwall/cli"; | ||
import { generateKeyringPair } from "@moonwall/util"; | ||
import { ApiPromise, Keyring } from "@polkadot/api"; | ||
import WebSocket from "ws"; | ||
|
||
const MAX_BALANCE_TRANSFER_TRIES = 5; | ||
|
||
export async function canCreateBlocks( | ||
context: ChopsticksContext, | ||
providerName: string, | ||
paraApi: ApiPromise | ||
) { | ||
const currentHeight = ( | ||
await paraApi.rpc.chain.getBlock() | ||
).block.header.number.toNumber(); | ||
await context.createBlock({ providerName: providerName, count: 2 }); | ||
const newHeight = ( | ||
await paraApi.rpc.chain.getBlock() | ||
).block.header.number.toNumber(); | ||
expect(newHeight - currentHeight, "Block difference is not correct!").toBe(2); | ||
} | ||
|
||
export async function canSendBalanceTransfer( | ||
context: ChopsticksContext, | ||
providerName: string, | ||
paraApi: ApiPromise | ||
) { | ||
const randomAccount = generateKeyringPair("sr25519"); | ||
const keyring = new Keyring({ type: "sr25519" }); | ||
const alice = keyring.addFromUri("//Alice", { name: "Alice default" }); | ||
|
||
let tries = 0; | ||
const amount = BigInt("1000000000"); | ||
const balanceBefore = ( | ||
await paraApi.query.system.account(randomAccount.address) | ||
).data.free.toBigInt(); | ||
|
||
/// It might happen that by accident we hit a session change | ||
/// A block in which a session change occurs cannot hold any tx | ||
/// Chopsticks does not have the notion of tx pool either, so we need to retry | ||
/// Therefore we just retry at most MAX_BALANCE_TRANSFER_TRIES | ||
while (tries < MAX_BALANCE_TRANSFER_TRIES) { | ||
const tx = await paraApi.tx.balances.transfer( | ||
randomAccount.address, | ||
amount | ||
); | ||
const txHash = tx.signAndSend(alice, { nonce: -1 }); | ||
const result = await context.createBlock({ | ||
providerName: providerName, | ||
count: 1, | ||
}); | ||
|
||
const block = await paraApi.rpc.chain.getBlock(result.result); | ||
const includedTxHashes = block.block.extrinsics.map((x) => | ||
x.hash.toString() | ||
); | ||
if (includedTxHashes.includes(txHash.toString())) { | ||
break; | ||
} | ||
tries++; | ||
} | ||
|
||
// without this, the xcm transfer test has a timeout | ||
await context.createBlock({ providerName: providerName, count: 1 }); | ||
|
||
const balanceAfter = ( | ||
await paraApi.query.system.account(randomAccount.address) | ||
).data.free.toBigInt(); | ||
expect(balanceAfter > balanceBefore, "Balance did not increase").toBeTruthy(); | ||
} | ||
|
||
export async function canSendXcmTransfer( | ||
log: Debugger, | ||
senderParaApi: ApiPromise, | ||
receiverParaApi: ApiPromise, | ||
receiverParaId: number, | ||
tokensIndex: number | ||
) { | ||
const keyring = new Keyring({ type: "sr25519" }); | ||
const alice = keyring.addFromUri("//Alice", { name: "Alice default" }); | ||
const bob = keyring.addFromUri("//Bob", { name: "Bob default" }); | ||
|
||
const senderBalanceBefore = ( | ||
await senderParaApi.query.system.account(alice.address) | ||
).data.free.toBigInt(); | ||
const receiverBalanceBefore = ( | ||
await receiverParaApi.query.tokens.accounts(bob.address, tokensIndex) | ||
).free.toBigInt(); | ||
|
||
const ztg = { Ztg: null }; | ||
const amount: bigint = BigInt("192913122185847181"); | ||
const bobAccountId = senderParaApi | ||
.createType("AccountId32", bob.address) | ||
.toHex(); | ||
const destination = { | ||
V3: { | ||
parents: 1, | ||
interior: { | ||
X2: [ | ||
{ Parachain: receiverParaId }, | ||
{ AccountId32: { id: bobAccountId, network: null } }, | ||
], | ||
}, | ||
}, | ||
}; | ||
const destWeightLimit = { Unlimited: null }; | ||
|
||
// Create a promise that resolves when the transaction is finalized | ||
const finalizedPromise = new Promise((resolve, reject) => { | ||
const xcmTransfer = senderParaApi.tx.xTokens.transfer( | ||
ztg, | ||
amount, | ||
destination, | ||
destWeightLimit | ||
); | ||
xcmTransfer.signAndSend(alice, { nonce: -1 }, ({ status }) => { | ||
log(`Current status is ${status.toString()}`); | ||
if (status.isFinalized) { | ||
log(`Transaction finalized at blockHash ${status.asFinalized}`); | ||
resolve(xcmTransfer); | ||
} else if (status.isError) { | ||
reject(new Error(`Transaction failed with status ${status}`)); | ||
} | ||
}); | ||
}); | ||
|
||
// Wait for the transaction to be finalized | ||
const xcmTransfer = await finalizedPromise; | ||
const { partialFee, weight } = await xcmTransfer.paymentInfo(alice.address); | ||
const transferFee: bigint = partialFee.toBigInt(); | ||
const senderBalanceAfter = ( | ||
await senderParaApi.query.system.account(alice.address) | ||
).data.free.toBigInt(); | ||
expect( | ||
senderBalanceBefore - senderBalanceAfter, | ||
"Unexpected balance diff" | ||
).toBe(amount + transferFee); | ||
|
||
// RpcError: 1: Block 0x... not found, if using this `await context.createBlock({ providerName: "ReceiverPara", count: 1 });` | ||
// Reported Bug here https://github.com/Moonsong-Labs/moonwall/issues/343 | ||
|
||
// use a workaround for creating a block | ||
const blocksToRun = 2; | ||
const currentHeight = ( | ||
await receiverParaApi.rpc.chain.getBlock() | ||
).block.header.number.toNumber(); | ||
const newBlockPromise = new Promise((resolve, reject) => { | ||
// ws://127.0.0.1:8001 represents the receiver chain endpoint | ||
const ws = new WebSocket("ws://127.0.0.1:8001"); | ||
|
||
ws.on("open", function open() { | ||
const message = { | ||
jsonrpc: "2.0", | ||
id: 1, | ||
method: "dev_newBlock", | ||
params: [{ count: blocksToRun }], | ||
}; | ||
|
||
ws.send(JSON.stringify(message)); | ||
}); | ||
|
||
ws.on("message", async function message(data) { | ||
const dataObj = JSON.parse(data.toString()); | ||
log("Received message:", dataObj); | ||
resolve(dataObj.result); | ||
}); | ||
|
||
ws.on("error", function error(error) { | ||
log("Error:", error.toString()); | ||
reject(error); | ||
}); | ||
}); | ||
|
||
const blockHash = await newBlockPromise; | ||
const newHeight = ( | ||
await receiverParaApi.rpc.chain.getBlock() | ||
).block.header.number.toNumber(); | ||
// TODO why +1 here? | ||
expect(newHeight - currentHeight, "Block difference is not correct!").toBe( | ||
blocksToRun + 1 | ||
); | ||
|
||
const receiverBalanceAfter: bigint = ( | ||
await receiverParaApi.query.tokens.accounts(bob.address, tokensIndex) | ||
).free.toBigInt(); | ||
expect( | ||
receiverBalanceAfter > receiverBalanceBefore, | ||
"Balance did not increase" | ||
).toBeTruthy(); | ||
const xcmFee: bigint = | ||
receiverBalanceBefore + amount - transferFee - receiverBalanceAfter; | ||
// between 0.03 ZTG and 0.05 ZTG XCM fee | ||
const approxXcmFeeLow = 300000000; | ||
const approxXcmFeeHigh = 500000000; | ||
expect(xcmFee).toBeGreaterThanOrEqual(approxXcmFeeLow); | ||
expect(xcmFee).toBeLessThanOrEqual(approxXcmFeeHigh); | ||
expect( | ||
receiverBalanceAfter - receiverBalanceBefore, | ||
"Unexpected xcm transfer balance diff" | ||
).toBe(amount - transferFee - xcmFee); | ||
} |
108 changes: 108 additions & 0 deletions
108
.../rt-upgrade-battery-station-chopsticks/test-battery-station-chopsticks-runtime-upgrade.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// Copyright (C) Moondance Labs Ltd. | ||
|
||
import { | ||
MoonwallContext, | ||
beforeAll, | ||
describeSuite, | ||
expect, | ||
} from "@moonwall/cli"; | ||
import { KeyringPair } from "@moonwall/util"; | ||
import { ApiPromise, Keyring } from "@polkadot/api"; | ||
import { | ||
canCreateBlocks, | ||
canSendBalanceTransfer, | ||
canSendXcmTransfer, | ||
} from "tests/common-tests"; | ||
|
||
const ZEITGEIST_TOKENS_INDEX = 12; | ||
const BASILISK_PARA_ID = 2090; | ||
describeSuite({ | ||
id: "CAN", | ||
title: "Chopsticks Battery Station Post-Upgrade Tests", | ||
foundationMethods: "chopsticks", | ||
testCases: function ({ it, context, log }) { | ||
let batteryStationParaApi: ApiPromise; | ||
let relayApi: ApiPromise; | ||
let basiliskParaApi: ApiPromise; | ||
let alice: KeyringPair; | ||
|
||
beforeAll(async () => { | ||
const keyring = new Keyring({ type: "sr25519" }); | ||
alice = keyring.addFromUri("//Alice", { name: "Alice default" }); | ||
batteryStationParaApi = context.polkadotJs("BatteryStationPara"); | ||
relayApi = context.polkadotJs("RococoRelay"); | ||
basiliskParaApi = context.polkadotJs("BasiliskPara"); | ||
|
||
const paraZeitgeistNetwork = | ||
batteryStationParaApi.consts.system.version.specName.toString(); | ||
expect(paraZeitgeistNetwork, "Para API incorrect").to.contain( | ||
"zeitgeist" | ||
); | ||
|
||
const relayNetwork = relayApi.consts.system.version.specName.toString(); | ||
expect(relayNetwork, "Relay API incorrect").to.contain("rococo"); | ||
|
||
const paraBasiliskNetwork = | ||
basiliskParaApi.consts.system.version.specName.toString(); | ||
expect(paraBasiliskNetwork, "Para API incorrect").to.contain("basilisk"); | ||
|
||
const rtBefore = | ||
batteryStationParaApi.consts.system.version.specVersion.toNumber(); | ||
log(`About to upgrade to runtime at:`); | ||
log(MoonwallContext.getContext().rtUpgradePath); | ||
|
||
await context.upgradeRuntime(context); | ||
|
||
const rtafter = | ||
batteryStationParaApi.consts.system.version.specVersion.toNumber(); | ||
log( | ||
`RT upgrade has increased specVersion from ${rtBefore} to ${rtafter}` | ||
); | ||
}); | ||
|
||
it({ | ||
id: "T1", | ||
timeout: 60000, | ||
title: "Can create new blocks", | ||
test: async () => { | ||
await canCreateBlocks( | ||
context, | ||
"BatteryStationPara", | ||
batteryStationParaApi | ||
); | ||
}, | ||
}); | ||
|
||
it({ | ||
id: "T2", | ||
timeout: 60000, | ||
title: "Can send balance transfers", | ||
test: async () => { | ||
await canSendBalanceTransfer( | ||
context, | ||
"BatteryStationPara", | ||
batteryStationParaApi | ||
); | ||
}, | ||
}); | ||
|
||
/* | ||
Currently not working, bug tracked here https://github.com/galacticcouncil/HydraDX-node/issues/725 | ||
it({ | ||
id: "T3", | ||
timeout: 60000, | ||
title: "Can send ZBS to Basilisk", | ||
test: async () => { | ||
await canSendXcmTransfer( | ||
log, | ||
batteryStationParaApi, | ||
basiliskParaApi, | ||
BASILISK_PARA_ID, | ||
ZEITGEIST_TOKENS_INDEX | ||
); | ||
}, | ||
}); | ||
*/ | ||
}, | ||
}); |
Oops, something went wrong.