const acalaConfig = await fetchConfig('acala')
acalaConfig.port = 8111 // set the port
acalaConfig.block = 4286000
acalaConfig.db = './db.sqlite'
const { chain, listenPort, close } = await setupWithServer(acalaConfig)
// This server can be accessed at wss://acalajs-examples--xlc.repl.co/
// Use https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Facalajs-examples--xlc.repl.co to connect to this testnet
console.log('Chopsticks is running on port', listenPort)
------------------------------------------- console -------------------------------------------
INFO (14701): Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/acala.yml
2023-08-23 14:22:26 REGISTRY: Unknown signed extensions SetEvmOrigin found, treating them as no-effect
Chopsticks is running on port 8111
INFO (rpc/14701): Acala RPC listening on port 8111
setup Acala api connect to the local testnet
const provider = new WsProvider(`ws://localhost:${listenPort}`)
const api = new ApiPromise({ provider, noInitWarn: true })
await api.isReady
add a couple helpers
// send a transaction and wait for it to be included
const sendTxAndWait = (tx) => {
return new Promise((resolve) => {
tx.send((status) => {
if (status.isInBlock || status.isFinalized) {
resolve(status.events)
}
})
})
}
// sign tx with a mock signature that will be accepted by Chopsticks
// so we can act on behalf of any accounts without the private key
// this requires mockSignatureHost to be enabled
const fakeSign = (tx, addr, nonce) => {
const mockSignature = new Uint8Array(64)
mockSignature.fill(0xcd)
mockSignature.set([0xde, 0xad, 0xbe, 0xef])
tx.signFake(addr, {
nonce,
genesisHash: api.genesisHash,
runtimeVersion: api.runtimeVersion,
blockHash: api.genesisHash,
})
// update fake signature
tx.signature.set(mockSignature)
return tx
}
setup wallet sdk and homa sdk
const wallet = new Wallet(api)
await wallet.isReady
const homa = new Homa(api, wallet)
await homa.isReady
// Bob
const testaddr = '246gNkjCexYRsCpdjtVhz35sHjcb21jpqipzT9u4uwKV8iEE'
// use Chopsticks to mint this user some ACA and DOT
await api.rpc('dev_setStorage', {
System: {
Account: [
[
// key
[testaddr],
// value
{
providers: 2, // 1 for ACA, 1 for DOT
data: {
free: 1000 * 1e12 // 1000 ACA
}
}
]
]
},
Tokens: {
Accounts: [
[
// key
[
testaddr,
{ Token: 'DOT' }
],
// value
{
free: 100 * 10e10 // 100 DOT
}
]
]
}
})
{
// create tx to use 100 DOT to mint LDOT
const tx = api.tx.homa.mint(100 * 10e10)
fakeSign(tx, testaddr, 0)
console.log('\nSend tx to use 100 DOT to mint LDOT')
const events = await sendTxAndWait(tx)
console.log('tx events', events.map(x => x.event.toHuman()))
}
const ldotBalance = (await api.query.tokens.accounts(testaddr, ldot)).free.toNumber()
console.log('\nMinted', ldotBalance / 1e10, 'LDOT')
------------------------------------------- console -------------------------------------------
Send tx to use 100 DOT to mint LDOT
INFO (block-builder/14701): Try building block #4,286,001
number: 4286001
extrinsicsCount: 1
umpCount: 0
tx events [
<many tx events>
]
Minted 7667.5245218183 LDOT
unstake LDOT
There are number of ways to unstake LDOT / convert it back to DOT
Slow unstake by wait for 28 days.
Use fast redeem by matching with new stakers. A fast redeem fee is charged. This is only available if there are DOT in the pending pool.
Use the Taiga tDOT pool to swap LDOT to DOT. A swap fee is charged. The swap rate depends on the pool balance
slow unstake
// unstake half
const unstakeAmount = Math.floor(ldotBalance / 2)
{
// create tx to unstake without fast redeem. i.e. wait for 28 days unstaking period
const tx = api.tx.homa.requestRedeem(unstakeAmount, false /* true to allow fast redeem if possible */)
fakeSign(tx, testaddr, 1)
console.log('Send tx to unstake', unstakeAmount / 1e10, 'LDOT')
const events = await sendTxAndWait(tx)
console.log('tx events', events.map(x => x.event.toHuman()))
}
// the redeem request is still pending and not yet enacted on relaychain
const pendingRedeemLDOT = (await api.query.homa.redeemRequests(testaddr))
console.log('\nPending redeem LDOT amount', pendingRedeemLDOT.toHuman())
const keyring = createTestKeyring()
const sudoKey = keyring.getPair('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY') // Alice
// simulate relaychain era bump
// this will trigger XCM to do unstake on relaychain
await sendTxAndWait(await api.tx.sudo.sudo(api.tx.homa.forceBumpCurrentEra(1)).signAsync(sudoKey))
const unbondings = await api.query.homa.unbondings.entries(testaddr)
console.log('\nUnbonding requests', unbondings.map(([key, value]) => [key.toHuman(), value.toHuman()]))
// bump 28 era so that the DOT is available for withdraw
await sendTxAndWait(await api.tx.sudo.sudo(api.tx.homa.forceBumpCurrentEra(28)).signAsync(sudoKey))
await sendTxAndWait(fakeSign(api.tx.homa.claimRedemption(testaddr /* any account can trigger redeem */), testaddr, 2))
const dotBalance = (await api.query.tokens.accounts(testaddr, { token: 'DOT'})).free.toNumber()
console.log('\nRedeemed', dotBalance / 1e10, 'DOT')
------------------------------------------- console -------------------------------------------
Send tx to unstake 3833.7622609091 LDOT
INFO (block-builder/14701): Block built
number: 4286001
hash: "0xaaec1a0bc862a76af6b53bcc60c7b62256487cce5c468828360950491d281d7f"
extrinsics: [
"0xbd0184008eaf04151687736326c9fea1…cdcdcdcd00000074000b00a0724e1809"
]
pendingExtrinsicsCount: 0
ump: {}
INFO (block-builder/14701): Try building block #4,286,002
number: 4286002
extrinsicsCount: 1
umpCount: 0
tx events [
<tx events>
]
Pending redeem LDOT amount [ '38,337,622,609,091', false ]
INFO (block-builder/14701): Block built
number: 4286002
hash: "0xed20da2f91d4a5f2d3104c2c25bd3005d965a4837e0ccb90f9bba865b6b0c2fd"
extrinsics: [
"0xc10184008eaf04151687736326c9fea1…cdcdcd00040074010bc38c602cde2200"
]
pendingExtrinsicsCount: 0
ump: {}
INFO (block-builder/14701): Try building block #4,286,003
number: 4286003
extrinsicsCount: 1
umpCount: 0
Unbonding requests [
[
[ '246gNkjCexYRsCpdjtVhz35sHjcb21jpqipzT9u4uwKV8iEE', '1,205' ],
'4,999,981,935,420'
]
]
INFO (block-builder/14701): Block built
number: 4286003
hash: "0xece387f4671b9245969411be150f01958642c28b8e663c8b374dc24941e361d4"
extrinsics: [
"0xbd018400d43593c715fdd31c61141abd…6d6e0a8924010000ff00740801000000"
]
pendingExtrinsicsCount: 0
ump: {}
INFO (block-builder/14701): Try building block #4,286,004
number: 4286004
extrinsicsCount: 1
umpCount: 0
INFO (block-builder/14701): Block built
number: 4286004
hash: "0x6509c89c4bb36e7181a0d0016ec80c74bed40faa967b0179d7c149d0e0212baf"
extrinsics: [
"0xbd018400d43593c715fdd31c61141abd…e53ea68134010400ff0074081c000000"
]
pendingExtrinsicsCount: 0
ump: {}
INFO (block-builder/14701): Try building block #4,286,005
number: 4286005
extrinsicsCount: 1
umpCount: 0
Redeemed 499.998193542 DOT
swap with taiga tDOT pool
use aggregatedDex to perform swap, which allow multiple step swap with both Taiga pool and Acala Dex pool in a single tx
const tx = api.tx.aggregatedDex.swapWithExactSupply(
[{Taiga: [/*pool id*/ 0, /*supply asset*/1, /*target asset*/0]}],
unstakeAmount,
0 // should always set a min target to prevent unexpected result
)
fakeSign(tx, testaddr, 3)
console.log('Send tx to swap', unstakeAmount / 1e10, 'LDOT')
const events = await sendTxAndWait(tx)
console.log('tx events', events.map(x => x.event.toHuman()))
------------------------------------------- console -------------------------------------------
Send tx to swap 3833.7622609091 LDOT
INFO (block-builder/14701): Block built
number: 4286005
hash: "0xf62a24768622c45aca7411c77df101dffb934f2a4d63dfd19dc3ff795e008f71"
extrinsics: [
"0x210284008eaf04151687736326c9fea1…87613693c912909cb226aa4794f26a48"
]
pendingExtrinsicsCount: 0
ump: {}
INFO (block-builder/14701): Try building block #4,286,006
number: 4286006
extrinsicsCount: 1
umpCount: 0
tx events [
<tx events>
]
INFO (block-builder/14701): Block built
number: 4286006
hash: "0xcd8e6b58affca45dae23d1321cf0ff22897d0ae8782c6703bcf31ccba8a0accb"
extrinsics: [
"0xf90184008eaf04151687736326c9fea1…01000000000000000bc38c602cde2200"
]
pendingExtrinsicsCount: 0
ump: {}