Skip to content

Commit 9fb6452

Browse files
committed
added auth_n_store with new smoldot
1 parent 79af6c4 commit 9fb6452

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import * as smoldot from 'smoldot';
2+
import { ApiPromise, WsProvider } from "@polkadot/api";
3+
import { Keyring } from "@polkadot/keyring";
4+
import { cryptoWaitReady } from '@polkadot/util-crypto';
5+
import { create } from 'ipfs-http-client';
6+
import { cidFromBytes } from './common.js';
7+
8+
9+
async function main() {
10+
await cryptoWaitReady();
11+
12+
// Alice's address - for transaction creation
13+
console.log('Connecting to Alice node for transaction creation...');
14+
const aliceWs = new WsProvider('ws://localhost:10000');
15+
const aliceApi = await ApiPromise.create({ provider: aliceWs });
16+
await aliceApi.isReady;
17+
18+
// Bob's address - to get the chainspec
19+
console.log('Fetching chainspec from Bob node...');
20+
const bobWs = new WsProvider('ws://localhost:12346');
21+
const bobApi = await ApiPromise.create({ provider: bobWs });
22+
await bobApi.isReady;
23+
24+
// Create keyring and accounts
25+
const keyring = new Keyring({ type: 'sr25519' });
26+
const sudoAccount = keyring.addFromUri('//Alice');
27+
const whoAccount = keyring.addFromUri('//Alice');
28+
29+
// Data
30+
const who = whoAccount.address;
31+
const transactions = 32;
32+
const bytes = 64 * 1024 * 1024; // 64 MB
33+
34+
// Prepare data for storage
35+
const dataToStore = "Hello, Bulletin with PAPI + Smoldot - " + new Date().toString();
36+
const cid = cidFromBytes(dataToStore);
37+
38+
// Start smoldot with logging enabled
39+
console.log('\n🚀 Starting smoldot...');
40+
const client = smoldot.start({
41+
maxLogLevel: 0, // 0=off, 1=error, 2=warn, 3=info, 4=debug, 5=trace
42+
logCallback: (level, target, message) => {
43+
const levelNames = ['ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE'];
44+
const levelName = levelNames[level - 1] || 'UNKNOWN';
45+
console.log(`[smoldot:${levelName}] ${target}: ${message}`);
46+
}
47+
});
48+
49+
// Get chain spec from Bob node and remove protocolId to allow smoldot to sync with local chain.
50+
const chainSpec = (await bobApi.rpc.syncstate.genSyncSpec(true)).toString();
51+
const chainSpecObj = JSON.parse(chainSpec);
52+
chainSpecObj.protocolId = null;
53+
const modifiedChainSpec = JSON.stringify(chainSpecObj);
54+
55+
await client
56+
.addChain({ chainSpec: modifiedChainSpec })
57+
.then(async (chain) => {
58+
// Give smoldot a moment to sync
59+
console.log("⏳ Waiting for smoldot to sync...");
60+
await new Promise(resolve => setTimeout(resolve, 12000));
61+
62+
const authorizeTx = aliceApi.tx.transactionStorage.authorizeAccount(
63+
who,
64+
transactions,
65+
bytes
66+
);
67+
const sudoTx = aliceApi.tx.sudo.sudo(authorizeTx);
68+
const signedAuthTx = await sudoTx.signAsync(sudoAccount);
69+
70+
const authBlockHash = await submitAndWatch(chain, signedAuthTx, 'authorizeAccount');
71+
console.log('✅ Authorized in block:', authBlockHash);
72+
73+
return chain;
74+
})
75+
.then(async (chain) => {
76+
const dataBytes = Buffer.from(dataToStore);
77+
const storeTx = aliceApi.tx.transactionStorage.store(dataBytes);
78+
const signedStoreTx = await storeTx.signAsync(whoAccount);
79+
80+
const storeBlockHash = await submitAndWatch(chain, signedStoreTx, 'store');
81+
console.log('✅ Stored data with CID:', cid);
82+
console.log(' In block:', storeBlockHash);
83+
84+
return chain;
85+
})
86+
.then(async () => {
87+
// Cleanup
88+
await aliceApi.disconnect();
89+
await bobApi.disconnect();
90+
})
91+
.then(() => client.terminate())
92+
.catch(async (error) => {
93+
console.error('Error while executing the example: ', error.message);
94+
await aliceApi.disconnect();
95+
await bobApi.disconnect();
96+
client.terminate();
97+
throw error;
98+
});
99+
}
100+
101+
async function submitAndWatch(chain, signedTx, description) {
102+
console.log(`✅ Signed ${description} transaction:`, signedTx.toHex());
103+
104+
// Submit transaction with watch
105+
chain.sendJsonRpc(`{"jsonrpc":"2.0","id":2,"method":"author_submitAndWatchExtrinsic","params":["${signedTx.toHex()}"]}`);
106+
107+
// Get subscription ID
108+
const response = await chain.nextJsonRpcResponse();
109+
const subscriptionId = JSON.parse(response).result;
110+
console.log(`${description} subscription ID:`, subscriptionId);
111+
112+
// Listen for transaction status updates
113+
while (true) {
114+
const statusUpdate = await chain.nextJsonRpcResponse();
115+
const parsed = JSON.parse(statusUpdate);
116+
console.log(`${description} transaction status:`, parsed);
117+
118+
// Check if transaction is in a block
119+
if (parsed.params?.result?.inBlock) {
120+
console.log(`✅ ${description} transaction included in block:`, parsed.params.result.inBlock);
121+
return parsed.params.result.inBlock;
122+
}
123+
124+
// Check for failure conditions
125+
if (parsed.params?.result === 'dropped' || parsed.params?.result === 'invalid') {
126+
throw new Error(`${description} transaction failed: ${parsed.params.result}`);
127+
}
128+
if (parsed.params?.result?.Invalid || parsed.params?.result?.Dropped) {
129+
throw new Error(`${description} transaction failed: ${JSON.stringify(parsed.params.result)}`);
130+
}
131+
}
132+
}
133+
134+
await main();

0 commit comments

Comments
 (0)