-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add transaction_v1 group of functions (#819)
* feat: add transaction_v1 group of functions * replace new block for awaiting a set amount of time. * change upgraded flag for providers * fix(rpc-test): await for RPC confirmation that the tx is included
- Loading branch information
Showing
4 changed files
with
120 additions
and
2 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 |
---|---|---|
@@ -1,9 +1,11 @@ | ||
import * as ChainHeadV1RPC from './chainHead_v1.js' | ||
import * as TransactionV1RPC from './transaction_v1.js' | ||
|
||
export { ChainHeadV1RPC } | ||
export { ChainHeadV1RPC, TransactionV1RPC } | ||
|
||
const handlers = { | ||
...ChainHeadV1RPC, | ||
...TransactionV1RPC, | ||
} | ||
|
||
export default handlers |
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,33 @@ | ||
import { Handler } from '../shared.js' | ||
import { HexString } from '@polkadot/util/types' | ||
import { defaultLogger } from '../../logger.js' | ||
|
||
const logger = defaultLogger.child({ name: 'rpc-transaction_v1' }) | ||
const randomId = () => Math.random().toString(36).substring(2) | ||
|
||
/** | ||
* Submit the extrinsic to the transaction pool | ||
* | ||
* @param context | ||
* @param params - [`extrinsic`] | ||
* | ||
* @return operation id | ||
*/ | ||
export const transaction_v1_broadcast: Handler<[HexString], string | null> = async (context, [extrinsic]) => { | ||
await context.chain.submitExtrinsic(extrinsic).catch((err) => { | ||
// As per the spec, the invalid transaction errors should be ignored. | ||
logger.warn('Submit extrinsic failed', err) | ||
}) | ||
|
||
return randomId() | ||
} | ||
|
||
/** | ||
* Stop broadcasting the transaction to other nodes. | ||
* | ||
*/ | ||
export const transaction_v1_stop: Handler<[string], null> = async (_context, [_operationId]) => { | ||
// Chopsticks doesn't have any process to broadcast the transaction through P2P | ||
// so stopping doesn't have any effect. | ||
return null | ||
} |
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,82 @@ | ||
import { ApiPromise } from '@polkadot/api' | ||
import { RuntimeContext } from '@polkadot-api/observable-client' | ||
import { describe, expect, it } from 'vitest' | ||
import { dev, env, observe, setupPolkadotApi, testingPairs } from './helper.js' | ||
import { firstValueFrom } from 'rxjs' | ||
|
||
const testApi = await setupPolkadotApi(env.acalaV15) | ||
|
||
const { alice, bob } = testingPairs() | ||
|
||
describe('transaction_v1', async () => { | ||
it('sends and executes transactions', async () => { | ||
const chainHead = testApi.observableClient.chainHead$() | ||
|
||
const api = await prepareChainForTx() | ||
|
||
const TRANSFERRED_VALUE = 100n | ||
const tx = await api.tx.balances.transferKeepAlive(bob.address, TRANSFERRED_VALUE).signAsync(alice) | ||
const { nextValue, subscription } = observe(chainHead.trackTx$(tx.toHex())) | ||
const resultPromise = nextValue() | ||
await new Promise((onSuccess, onError) => | ||
testApi.substrateClient._request('transaction_v1_broadcast', [tx.toHex()], { onSuccess, onError }), | ||
) | ||
const hash = await dev.newBlock() | ||
|
||
expect(await resultPromise).toMatchObject({ | ||
hash, | ||
found: { | ||
type: true, | ||
}, | ||
}) | ||
|
||
const keyEncoder = (addr: string) => (ctx: RuntimeContext) => | ||
ctx.dynamicBuilder.buildStorage('System', 'Account').enc(addr) | ||
const resultDecoder = (data: string | null, ctx: RuntimeContext) => | ||
data ? ctx.dynamicBuilder.buildStorage('System', 'Account').dec(data) : null | ||
expect( | ||
await firstValueFrom(chainHead.storage$(null, 'value', keyEncoder(bob.address), null, resultDecoder)), | ||
).toMatchObject({ | ||
data: { | ||
free: INITIAL_ACCOUNT_VALUE + TRANSFERRED_VALUE, | ||
}, | ||
}) | ||
|
||
subscription.unsubscribe() | ||
chainHead.unfollow() | ||
}) | ||
}) | ||
|
||
const INITIAL_ACCOUNT_VALUE = 100_000_000_000_000n | ||
async function prepareChainForTx() { | ||
const api = await ApiPromise.create({ | ||
provider: testApi.ws, | ||
noInitWarn: true, | ||
}) | ||
await api.isReady | ||
await dev.setStorage({ | ||
System: { | ||
Account: [ | ||
[ | ||
[alice.address], | ||
{ | ||
providers: 1, | ||
data: { free: INITIAL_ACCOUNT_VALUE }, | ||
}, | ||
], | ||
[ | ||
[bob.address], | ||
{ | ||
providers: 1, | ||
data: { free: INITIAL_ACCOUNT_VALUE }, | ||
}, | ||
], | ||
], | ||
}, | ||
Sudo: { | ||
Key: alice.address, | ||
}, | ||
}) | ||
|
||
return api | ||
} |