@@ -0,0 +1,127 @@
const { ApiPromise, WsProvider } = require ( '@polkadot/api' ) ;
const { Keyring } = require ( '@polkadot/keyring' ) ;
const {
construct,
decode,
deriveAddress,
getRegistry,
methods,
PolkadotSS58Format,
} = require ( '@substrate/txwrapper-polkadot' ) ;
const { cryptoWaitReady } = require ( '@polkadot/util-crypto' ) ;
const fetch = require ( 'node-fetch' ) ;
const { createMetadata, OptionsWithMeta } = require ( '@substrate/txwrapper-polkadot' ) ;
const { EXTRINSIC_VERSION } = require ( '@polkadot/types/extrinsic/v4/Extrinsic' ) ;
async function rpcToLocalNode (
method ,
params
) {
return await fetch ( 'http://localhost:9933' , {
body : JSON . stringify ( {
id : 1 ,
jsonrpc : '2.0' ,
method,
params,
} ) ,
headers : {
'Content-Type' : 'application/json' ,
} ,
method : 'POST' ,
} )
. then ( ( response ) => response . json ( ) )
. then ( ( { error, result } ) => {
if ( error ) {
throw new Error (
`${ error . code } ${ error . message } : ${ JSON . stringify ( error . data ) } `
) ;
}
return result ;
} ) ;
}
async function signWith (
pair ,
signingPayload ,
options
) {
const { registry, metadataRpc } = options ;
// Important! The registry needs to be updated with latest metadata, so make
// sure to run `registry.setMetadata(metadata)` before signing.
registry . setMetadata ( createMetadata ( registry , metadataRpc ) ) ;
const { signature } = registry
. createType ( 'ExtrinsicPayload' , signingPayload , {
version : EXTRINSIC_VERSION ,
} )
. sign ( pair ) ;
return signature ;
}
async function test5 ( ) {
await cryptoWaitReady ( ) ;
const keyring = new Keyring ( { type : 'sr25519' } ) ;
// Add Alice to our keyring with a hard-deived path (empty phrase, so uses dev)
const alice = keyring . addFromUri ( '//Alice' ) ;
const bob = keyring . addFromUri ( '//Bob' ) ;
const { specVersion, transactionVersion, specName } = await rpcToLocalNode (
'state_getRuntimeVersion'
) ;
const { block } = await rpcToLocalNode ( 'chain_getBlock' ) ;
const blockHash = await rpcToLocalNode ( 'chain_getBlockHash' ) ;
const genesisHash = await rpcToLocalNode ( 'chain_getBlockHash' , [ 0 ] ) ;
const metadataRpc = await rpcToLocalNode ( 'state_getMetadata' ) ;
// const index = await httpRequest({ ...params, method: 'system_accountNextIndex', params: [pair.address] });
const index = await rpcToLocalNode ( 'system_accountNextIndex' , [ alice . address ] ) ;
const registry = getRegistry ( {
chainName : 'Polkadot' ,
specName,
specVersion,
metadataRpc,
} ) ;
const unsigned = methods . balances . transfer (
{
dest : bob . address ,
value : 100 ,
} ,
{
address : deriveAddress ( alice . publicKey , PolkadotSS58Format . polkadot ) ,
blockHash,
blockNumber : registry
. createType ( 'BlockNumber' , block . header . number )
. toNumber ( ) ,
eraPeriod : 64 ,
genesisHash,
metadataRpc,
nonce : index , // Assuming this is Alice's first tx on the chain
specVersion,
tip : 0 ,
transactionVersion,
} ,
{ metadataRpc, registry }
) ;
const signingPayload = construct . signingPayload ( unsigned , { registry } ) ;
// On your offline device, sign the payload.
// const signature = myOfflineSigning(signingPayload);
const signature = await signWith ( alice , signingPayload , {
metadataRpc,
registry,
} ) ;
// `tx` is ready to be broadcasted.
const tx = construct . signedTx ( unsigned , signature , { metadataRpc, registry } ) ;
console . log ( 'tx' , tx ) ;
const actualTxHash = await rpcToLocalNode ( 'author_submitExtrinsic' , [ tx ] ) ;
console . log ( `Actual Tx Hash: ${ actualTxHash } ` ) ;
console . log ( 'block_hash' , blockHash , block , index ) ;
}
test5 ( )