@novasamatech/sdk-statement 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/esm/api.mjs +12 -0
- package/dist/esm/api.mjs.map +1 -0
- package/dist/esm/codec/codec.mjs +75 -0
- package/dist/esm/codec/codec.mjs.map +1 -0
- package/dist/esm/index.mjs +5 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/signer.mjs +24 -0
- package/dist/esm/signer.mjs.map +1 -0
- package/dist/esm/statement-sdk.mjs +90 -0
- package/dist/esm/statement-sdk.mjs.map +1 -0
- package/dist/esm/utils.mjs +32 -0
- package/dist/esm/utils.mjs.map +1 -0
- package/dist/index.d.ts +261 -0
- package/dist/index.js +225 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @polkadot-api/sdk-statement
|
package/dist/esm/api.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const getApi = (req, subscribe) => ({
|
|
2
|
+
submit: (stmt) => req("statement_submit", [stmt]),
|
|
3
|
+
subscribeStatement: (topicFilter, onMessage, onError) => subscribe(
|
|
4
|
+
"statement_subscribeStatement",
|
|
5
|
+
[topicFilter],
|
|
6
|
+
onMessage,
|
|
7
|
+
onError
|
|
8
|
+
)
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export { getApi };
|
|
12
|
+
//# sourceMappingURL=api.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.mjs","sources":["../../src/api.ts"],"sourcesContent":["import { HexString } from \"@polkadot-api/substrate-bindings\"\nimport { SubmitResult, TopicFilter, StatementEvent } from \"./types\"\n\nexport type RequestFn = <Reply = any, Params extends Array<any> = any[]>(\n method: string,\n params: Params,\n) => Promise<Reply>\n\nexport type SubscribeFn = <T = any, Params extends Array<any> = any[]>(\n method: string,\n params: Params,\n onMessage: (message: T) => void,\n onError: (error: Error) => void,\n) => () => void\n\nexport const getApi = (req: RequestFn, subscribe: SubscribeFn) => ({\n submit: (stmt: HexString) =>\n req<SubmitResult, [HexString]>(\"statement_submit\", [stmt]),\n\n subscribeStatement: (\n topicFilter: TopicFilter,\n onMessage: (event: StatementEvent) => void,\n onError: (error: Error) => void,\n ) =>\n subscribe<StatementEvent, [TopicFilter]>(\n \"statement_subscribeStatement\",\n [topicFilter],\n onMessage,\n onError,\n ),\n})\n"],"names":[],"mappings":"AAeO,MAAM,MAAA,GAAS,CAAC,GAAA,EAAgB,SAAA,MAA4B;AAAA,EACjE,QAAQ,CAAC,IAAA,KACP,IAA+B,kBAAA,EAAoB,CAAC,IAAI,CAAC,CAAA;AAAA,EAE3D,kBAAA,EAAoB,CAClB,WAAA,EACA,SAAA,EACA,OAAA,KAEA,SAAA;AAAA,IACE,8BAAA;AAAA,IACA,CAAC,WAAW,CAAA;AAAA,IACZ,SAAA;AAAA,IACA;AAAA;AAEN,CAAA;;;;"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { SizedBytes, Variant, u64, Bytes, Struct, Vector, enhanceCodec, Enum } from '@polkadot-api/substrate-bindings';
|
|
2
|
+
|
|
3
|
+
const sortIdxs = {
|
|
4
|
+
proof: 0,
|
|
5
|
+
decryptionKey: 1,
|
|
6
|
+
expiry: 2,
|
|
7
|
+
channel: 3,
|
|
8
|
+
topics: 4,
|
|
9
|
+
topic1: 4,
|
|
10
|
+
topic2: 5,
|
|
11
|
+
topic3: 6,
|
|
12
|
+
topic4: 7,
|
|
13
|
+
data: 8
|
|
14
|
+
};
|
|
15
|
+
const bin32 = SizedBytes(32);
|
|
16
|
+
const bin64 = SizedBytes(64);
|
|
17
|
+
const field = Variant({
|
|
18
|
+
proof: Variant({
|
|
19
|
+
sr25519: Struct({ signature: bin64, signer: bin32 }),
|
|
20
|
+
ed25519: Struct({ signature: bin64, signer: bin32 }),
|
|
21
|
+
ecdsa: Struct({ signature: SizedBytes(65), signer: SizedBytes(33) }),
|
|
22
|
+
onChain: Struct({ who: bin32, blockHash: bin32, event: u64 })
|
|
23
|
+
}),
|
|
24
|
+
decryptionKey: bin32,
|
|
25
|
+
expiry: u64,
|
|
26
|
+
channel: bin32,
|
|
27
|
+
topic1: bin32,
|
|
28
|
+
topic2: bin32,
|
|
29
|
+
topic3: bin32,
|
|
30
|
+
topic4: bin32,
|
|
31
|
+
data: Bytes()
|
|
32
|
+
});
|
|
33
|
+
const innerStatement = Vector(field);
|
|
34
|
+
const statementCodec = enhanceCodec(
|
|
35
|
+
innerStatement,
|
|
36
|
+
(stmt) => {
|
|
37
|
+
const statement = [];
|
|
38
|
+
Object.keys(stmt).sort((a, b) => sortIdxs[a] - sortIdxs[b]).forEach((k) => {
|
|
39
|
+
if (k === "topics") {
|
|
40
|
+
if (stmt[k].length > 4)
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Max topics length is 4. Received ${stmt[k]?.length}`
|
|
43
|
+
);
|
|
44
|
+
stmt[k].forEach((v, i) => {
|
|
45
|
+
statement.push(Enum(`topic${i + 1}`, v));
|
|
46
|
+
});
|
|
47
|
+
} else {
|
|
48
|
+
statement.push(Enum(k, stmt[k]));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return statement;
|
|
52
|
+
},
|
|
53
|
+
(stmt) => {
|
|
54
|
+
const statement = {};
|
|
55
|
+
let maxTopicChecked = 0;
|
|
56
|
+
let maxIdx = -1;
|
|
57
|
+
stmt.forEach((v) => {
|
|
58
|
+
const idx = sortIdxs[v.type];
|
|
59
|
+
if (idx <= maxIdx) throw new Error("Unexpected entries order");
|
|
60
|
+
maxIdx = idx;
|
|
61
|
+
if (!v.type.startsWith("topic")) {
|
|
62
|
+
statement[v.type] = v.value;
|
|
63
|
+
} else if (v.type !== `topic${++maxTopicChecked}`) {
|
|
64
|
+
throw new Error(`Unexpected ${v.type}`);
|
|
65
|
+
} else {
|
|
66
|
+
statement.topics ?? (statement.topics = []);
|
|
67
|
+
statement.topics?.push(v.value);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return statement;
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
export { statementCodec };
|
|
75
|
+
//# sourceMappingURL=codec.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.mjs","sources":["../../../src/codec/codec.ts"],"sourcesContent":["import {\n Bytes,\n CodecType,\n enhanceCodec,\n Enum,\n HexString,\n SizedBytes,\n SizedHex,\n Struct,\n u64,\n Variant,\n Vector,\n} from \"@polkadot-api/substrate-bindings\"\n\nexport type Proof = Enum<{\n sr25519: { signature: SizedHex<64>; signer: SizedHex<32> }\n ed25519: { signature: SizedHex<64>; signer: SizedHex<32> }\n ecdsa: { signature: SizedHex<65>; signer: SizedHex<33> }\n onChain: {\n who: SizedHex<32>\n blockHash: SizedHex<32>\n event: bigint\n }\n}>\n\nexport type Statement = Partial<{\n proof: Proof\n /** @deprecated Experimental feature, may be removed/changed in future releases */\n decryptionKey: SizedHex<32>\n expiry: bigint\n channel: SizedHex<32>\n topics: Array<SizedHex<32>>\n data: Uint8Array\n}>\n\nconst sortIdxs = {\n proof: 0,\n decryptionKey: 1,\n expiry: 2,\n channel: 3,\n topics: 4,\n topic1: 4,\n topic2: 5,\n topic3: 6,\n topic4: 7,\n data: 8,\n}\n\nexport type UnsignedStatement = Omit<Statement, \"proof\">\nexport type SignedStatement = UnsignedStatement & { proof: Proof }\n\nconst bin32 = SizedBytes(32)\nconst bin64 = SizedBytes(64)\n\nconst field = Variant({\n proof: Variant({\n sr25519: Struct({ signature: bin64, signer: bin32 }),\n ed25519: Struct({ signature: bin64, signer: bin32 }),\n ecdsa: Struct({ signature: SizedBytes(65), signer: SizedBytes(33) }),\n onChain: Struct({ who: bin32, blockHash: bin32, event: u64 }),\n }),\n decryptionKey: bin32,\n expiry: u64,\n channel: bin32,\n topic1: bin32,\n topic2: bin32,\n topic3: bin32,\n topic4: bin32,\n data: Bytes(),\n})\nconst innerStatement = Vector(field)\n\nexport const statementCodec = enhanceCodec<\n CodecType<typeof innerStatement>,\n Statement\n>(\n innerStatement,\n (stmt) => {\n const statement: CodecType<typeof innerStatement> = []\n ;(Object.keys(stmt) as Array<keyof Statement>)\n .sort((a, b) => sortIdxs[a] - sortIdxs[b])\n .forEach((k) => {\n if (k === \"topics\") {\n if (stmt[k]!.length > 4)\n throw new Error(\n `Max topics length is 4. Received ${stmt[k]?.length}`,\n )\n stmt[k]!.forEach((v, i) => {\n statement.push(Enum(`topic${i + 1}` as `topic${1 | 2 | 3 | 4}`, v))\n })\n } else {\n statement.push(Enum(k, stmt[k]!))\n }\n })\n return statement\n },\n (stmt) => {\n const statement: Statement = {}\n let maxTopicChecked = 0\n let maxIdx = -1\n stmt.forEach((v) => {\n // ensure order and no repetition\n const idx = sortIdxs[v.type]\n if (idx <= maxIdx) throw new Error(\"Unexpected entries order\")\n maxIdx = idx\n\n if (!v.type.startsWith(\"topic\")) {\n ;(statement as any)[v.type] = v.value\n } else if (v.type !== `topic${++maxTopicChecked}`) {\n throw new Error(`Unexpected ${v.type}`)\n } else {\n statement.topics ??= []\n statement.topics?.push(v.value as HexString)\n }\n })\n return statement\n },\n)\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { statementCodec } from './codec/codec.mjs';
|
|
2
|
+
export { createStatementSdk } from './statement-sdk.mjs';
|
|
3
|
+
export { getStatementSigner } from './signer.mjs';
|
|
4
|
+
export { createExpiry, createExpiryFromDuration, isExpired, parseExpiry, stringToTopic } from './utils.mjs';
|
|
5
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { compact, Enum } from '@polkadot-api/substrate-bindings';
|
|
2
|
+
import { Binary } from 'polkadot-api';
|
|
3
|
+
import { statementCodec } from './codec/codec.mjs';
|
|
4
|
+
|
|
5
|
+
const getStatementSigner = (publicKey, type, signFn) => ({
|
|
6
|
+
publicKey,
|
|
7
|
+
sign: async (stmt) => {
|
|
8
|
+
if (stmt.proof) throw new Error("Statement already signed");
|
|
9
|
+
const encoded = statementCodec.enc(stmt);
|
|
10
|
+
const compactLen = compact.enc(compact.dec(encoded)).length;
|
|
11
|
+
const signature = await signFn(encoded.slice(compactLen));
|
|
12
|
+
const result = statementCodec.dec(encoded);
|
|
13
|
+
result.proof = Enum(type, {
|
|
14
|
+
signature: Binary.toHex(signature),
|
|
15
|
+
// SizedHex<64> or SizedHex<65>
|
|
16
|
+
signer: Binary.toHex(publicKey)
|
|
17
|
+
// SizedHex<32> or SizedHex<33>
|
|
18
|
+
});
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export { getStatementSigner };
|
|
24
|
+
//# sourceMappingURL=signer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signer.mjs","sources":["../../src/signer.ts"],"sourcesContent":["import { compact, Enum } from \"@polkadot-api/substrate-bindings\"\nimport { Binary } from \"polkadot-api\"\nimport { SignedStatement, Statement, statementCodec } from \"./codec\"\n\nexport const getStatementSigner = (\n publicKey: Uint8Array,\n type: \"ed25519\" | \"sr25519\" | \"ecdsa\",\n signFn: (payload: Uint8Array) => Promise<Uint8Array> | Uint8Array,\n) => ({\n publicKey,\n sign: async (stmt: Statement): Promise<SignedStatement> => {\n if (stmt.proof) throw new Error(\"Statement already signed\")\n const encoded = statementCodec.enc(stmt)\n const compactLen = compact.enc(compact.dec(encoded)).length\n const signature = await signFn(encoded.slice(compactLen))\n const result = statementCodec.dec(encoded)\n result.proof = Enum(type, {\n signature: Binary.toHex(signature) as any, // SizedHex<64> or SizedHex<65>\n signer: Binary.toHex(publicKey) as any, // SizedHex<32> or SizedHex<33>\n })\n return result as SignedStatement\n },\n})\n"],"names":[],"mappings":";;;;AAIO,MAAM,kBAAA,GAAqB,CAChC,SAAA,EACA,IAAA,EACA,MAAA,MACI;AAAA,EACJ,SAAA;AAAA,EACA,IAAA,EAAM,OAAO,IAAA,KAA8C;AACzD,IAAA,IAAI,IAAA,CAAK,KAAA,EAAO,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAC1D,IAAA,MAAM,OAAA,GAAU,cAAA,CAAe,GAAA,CAAI,IAAI,CAAA;AACvC,IAAA,MAAM,aAAa,OAAA,CAAQ,GAAA,CAAI,QAAQ,GAAA,CAAI,OAAO,CAAC,CAAA,CAAE,MAAA;AACrD,IAAA,MAAM,YAAY,MAAM,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,UAAU,CAAC,CAAA;AACxD,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,GAAA,CAAI,OAAO,CAAA;AACzC,IAAA,MAAA,CAAO,KAAA,GAAQ,KAAK,IAAA,EAAM;AAAA,MACxB,SAAA,EAAW,MAAA,CAAO,KAAA,CAAM,SAAS,CAAA;AAAA;AAAA,MACjC,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,SAAS;AAAA;AAAA,KAC/B,CAAA;AACD,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAA;;;;"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { statementCodec } from './codec/codec.mjs';
|
|
2
|
+
import { toHex } from '@polkadot-api/utils';
|
|
3
|
+
import { getApi } from './api.mjs';
|
|
4
|
+
import { filterDecKey } from './utils.mjs';
|
|
5
|
+
|
|
6
|
+
const ANY_FILTER = "any";
|
|
7
|
+
const createStatementSdk = (req, subscribe) => {
|
|
8
|
+
const api = getApi(req, subscribe);
|
|
9
|
+
const getStatements = (filter = ANY_FILTER) => new Promise((resolve, reject) => {
|
|
10
|
+
const statements = [];
|
|
11
|
+
const unsubscribe = api.subscribeStatement(
|
|
12
|
+
filter,
|
|
13
|
+
(event) => {
|
|
14
|
+
if (event.event === "newStatements") {
|
|
15
|
+
for (const encoded of event.data.statements) {
|
|
16
|
+
try {
|
|
17
|
+
statements.push(statementCodec.dec(encoded));
|
|
18
|
+
} catch (e) {
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (event.data.remaining === 0 || event.data.remaining === void 0) {
|
|
22
|
+
unsubscribe();
|
|
23
|
+
resolve(statements);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
(error) => {
|
|
28
|
+
unsubscribe();
|
|
29
|
+
reject(error);
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
/**
|
|
35
|
+
* Submit a Statement to the store.
|
|
36
|
+
* It must be signed to be accepted.
|
|
37
|
+
*/
|
|
38
|
+
submit: (stmt) => api.submit(toHex(statementCodec.enc(stmt))),
|
|
39
|
+
getStatements,
|
|
40
|
+
/**
|
|
41
|
+
* Subscribe to statements matching the given filter.
|
|
42
|
+
*
|
|
43
|
+
* Unlike `getStatements`, this maintains an active subscription and
|
|
44
|
+
* continues to receive new statements as they are added to the store.
|
|
45
|
+
*
|
|
46
|
+
* @param filter Topic filter for statements.
|
|
47
|
+
* @param onStatement Callback for each decoded statement.
|
|
48
|
+
* @param onError Callback for errors.
|
|
49
|
+
* @returns Unsubscribe function.
|
|
50
|
+
*/
|
|
51
|
+
subscribeStatements: (filter, onStatement, onError) => api.subscribeStatement(
|
|
52
|
+
filter,
|
|
53
|
+
(event) => {
|
|
54
|
+
if (event.event === "newStatements") {
|
|
55
|
+
for (const encoded of event.data.statements) {
|
|
56
|
+
try {
|
|
57
|
+
onStatement(statementCodec.dec(encoded));
|
|
58
|
+
} catch (e) {
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
onError
|
|
64
|
+
),
|
|
65
|
+
/**
|
|
66
|
+
* Get broadcasts (statements with no decryptionKey) matching topics.
|
|
67
|
+
*
|
|
68
|
+
* @param topics Topics to match (all must be present).
|
|
69
|
+
*/
|
|
70
|
+
getBroadcasts: async (topics = []) => {
|
|
71
|
+
const filter = topics.length > 0 ? { matchAll: topics } : ANY_FILTER;
|
|
72
|
+
const statements = await getStatements(filter);
|
|
73
|
+
return statements.filter((stmt) => stmt.decryptionKey === void 0);
|
|
74
|
+
},
|
|
75
|
+
/**
|
|
76
|
+
* Get posted statements (with decryptionKey) matching topics and destination.
|
|
77
|
+
*
|
|
78
|
+
* @param topics Topics to match (all must be present).
|
|
79
|
+
* @param dest Destination decryption key.
|
|
80
|
+
*/
|
|
81
|
+
getPosted: async (topics, dest) => {
|
|
82
|
+
const filter = topics.length > 0 ? { matchAll: topics } : ANY_FILTER;
|
|
83
|
+
const statements = await getStatements(filter);
|
|
84
|
+
return statements.filter(filterDecKey(dest));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export { createStatementSdk };
|
|
90
|
+
//# sourceMappingURL=statement-sdk.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statement-sdk.mjs","sources":["../../src/statement-sdk.ts"],"sourcesContent":["import { SizedHex } from \"@polkadot-api/substrate-bindings\"\nimport { Statement, statementCodec } from \"./codec\"\nimport { toHex } from \"@polkadot-api/utils\"\nimport { getApi, RequestFn, SubscribeFn } from \"./api\"\nimport { filterDecKey } from \"./utils\"\nimport { SubmitResult, TopicFilter, StatementEvent } from \"./types\"\n\nconst ANY_FILTER: TopicFilter = \"any\"\n\n/**\n * Create statement sdk.\n *\n * @param {RequestFn} req Takes a req-res function, which accepts Statement RPC\n * calls. This can be `client._request` (from\n * `polkadot-api`) client, `client.request` (from\n * `@polkadot-api/substrate-client`)\n * or any other crafted by the consumer.\n * @param {SubscribeFn} subscribe Takes a subscription function for RPC subscriptions.\n * This can be `client._subscribe` (from `polkadot-api`)\n * or any other crafted by the consumer.\n */\nexport const createStatementSdk = (req: RequestFn, subscribe: SubscribeFn) => {\n const api = getApi(req, subscribe)\n\n /**\n * Get statements from store matching the given filter.\n *\n * This method subscribes to the statement store, collects all existing\n * statements matching the filter, then unsubscribes and returns them.\n *\n * @param filter Topic filter for statements. Defaults to matching all.\n */\n const getStatements = (\n filter: TopicFilter = ANY_FILTER,\n ): Promise<Statement[]> =>\n new Promise((resolve, reject) => {\n const statements: Statement[] = []\n\n const unsubscribe = api.subscribeStatement(\n filter,\n (event: StatementEvent) => {\n if (event.event === \"newStatements\") {\n for (const encoded of event.data.statements) {\n try {\n statements.push(statementCodec.dec(encoded))\n } catch (e) {\n // Skip malformed statements\n }\n }\n\n // Initial dump complete when remaining is 0 or undefined\n if (\n event.data.remaining === 0 ||\n event.data.remaining === undefined\n ) {\n unsubscribe()\n resolve(statements)\n }\n }\n },\n (error: Error) => {\n unsubscribe()\n reject(error)\n },\n )\n })\n\n return {\n /**\n * Submit a Statement to the store.\n * It must be signed to be accepted.\n */\n submit: (stmt: Statement): Promise<SubmitResult> =>\n api.submit(toHex(statementCodec.enc(stmt))),\n\n getStatements,\n\n /**\n * Subscribe to statements matching the given filter.\n *\n * Unlike `getStatements`, this maintains an active subscription and\n * continues to receive new statements as they are added to the store.\n *\n * @param filter Topic filter for statements.\n * @param onStatement Callback for each decoded statement.\n * @param onError Callback for errors.\n * @returns Unsubscribe function.\n */\n subscribeStatements: (\n filter: TopicFilter,\n onStatement: (statement: Statement) => void,\n onError: (error: Error) => void,\n ): (() => void) =>\n api.subscribeStatement(\n filter,\n (event: StatementEvent) => {\n if (event.event === \"newStatements\") {\n for (const encoded of event.data.statements) {\n try {\n onStatement(statementCodec.dec(encoded))\n } catch (e) {\n // Skip malformed statements\n }\n }\n }\n },\n onError,\n ),\n\n /**\n * Get broadcasts (statements with no decryptionKey) matching topics.\n *\n * @param topics Topics to match (all must be present).\n */\n getBroadcasts: async (\n topics: Array<SizedHex<32>> = [],\n ): Promise<Statement[]> => {\n const filter: TopicFilter =\n topics.length > 0 ? { matchAll: topics } : ANY_FILTER\n const statements = await getStatements(filter)\n return statements.filter((stmt) => stmt.decryptionKey === undefined)\n },\n\n /**\n * Get posted statements (with decryptionKey) matching topics and destination.\n *\n * @param topics Topics to match (all must be present).\n * @param dest Destination decryption key.\n */\n getPosted: async (\n topics: Array<SizedHex<32>>,\n dest: SizedHex<32>,\n ): Promise<Statement[]> => {\n const filter: TopicFilter =\n topics.length > 0 ? { matchAll: topics } : ANY_FILTER\n const statements = await getStatements(filter)\n return statements.filter(filterDecKey(dest))\n },\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Binary, Blake2256 } from '@polkadot-api/substrate-bindings';
|
|
2
|
+
|
|
3
|
+
const stringToTopic = (str) => {
|
|
4
|
+
const enc = Binary.fromText(str);
|
|
5
|
+
return Binary.toHex(Blake2256(enc));
|
|
6
|
+
};
|
|
7
|
+
const filterDecKey = (key) => {
|
|
8
|
+
if (!key) return () => true;
|
|
9
|
+
const hexKey = key;
|
|
10
|
+
return (v) => v.decryptionKey === hexKey;
|
|
11
|
+
};
|
|
12
|
+
const createExpiry = (expirationTimestampSecs, sequenceNumber = 0) => {
|
|
13
|
+
if (sequenceNumber < 0 || sequenceNumber > 4294967295) {
|
|
14
|
+
throw new RangeError("sequenceNumber must be 0-4294967295");
|
|
15
|
+
}
|
|
16
|
+
return BigInt(expirationTimestampSecs) << 32n | BigInt(sequenceNumber);
|
|
17
|
+
};
|
|
18
|
+
const parseExpiry = (expiry) => ({
|
|
19
|
+
timestamp: Number(expiry >> 32n),
|
|
20
|
+
sequence: Number(expiry & 0xffffffffn)
|
|
21
|
+
});
|
|
22
|
+
const createExpiryFromDuration = (durationSecs, sequenceNumber = 0) => {
|
|
23
|
+
const timestamp = Math.floor(Date.now() / 1e3) + durationSecs;
|
|
24
|
+
return createExpiry(timestamp, sequenceNumber);
|
|
25
|
+
};
|
|
26
|
+
const isExpired = (expiry) => {
|
|
27
|
+
const { timestamp } = parseExpiry(expiry);
|
|
28
|
+
return timestamp < Math.floor(Date.now() / 1e3);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { createExpiry, createExpiryFromDuration, filterDecKey, isExpired, parseExpiry, stringToTopic };
|
|
32
|
+
//# sourceMappingURL=utils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.mjs","sources":["../../src/utils.ts"],"sourcesContent":["import { Binary, Blake2256, SizedHex } from \"@polkadot-api/substrate-bindings\"\nimport { Statement } from \"./codec\"\n\nexport const stringToTopic = (str: string): SizedHex<32> => {\n const enc = Binary.fromText(str) // Returns Uint8Array directly\n return Binary.toHex(Blake2256(enc)) as SizedHex<32> // SizedHex is now SizedHex (string)\n}\n\nexport const filterDecKey = (key?: SizedHex<32>) => {\n if (!key) return () => true\n const hexKey = key // Already a hex string (SizedHex)\n return (v: Statement) => v.decryptionKey === hexKey\n}\n\n/**\n * Create an expiry value from timestamp and sequence number.\n *\n * @param expirationTimestampSecs Expiration time in seconds since UNIX epoch.\n * @param sequenceNumber Sequence number for ordering (0-4294967295).\n */\nexport const createExpiry = (\n expirationTimestampSecs: number,\n sequenceNumber: number = 0,\n): bigint => {\n if (sequenceNumber < 0 || sequenceNumber > 0xffffffff) {\n throw new RangeError(\"sequenceNumber must be 0-4294967295\")\n }\n return (BigInt(expirationTimestampSecs) << 32n) | BigInt(sequenceNumber)\n}\n\n/**\n * Parse an expiry value into its components.\n *\n * @param expiry The expiry value to parse.\n */\nexport const parseExpiry = (\n expiry: bigint,\n): { timestamp: number; sequence: number } => ({\n timestamp: Number(expiry >> 32n),\n sequence: Number(expiry & 0xffffffffn),\n})\n\n/**\n * Create an expiry value that expires after a given duration.\n *\n * @param durationSecs Duration in seconds from now.\n * @param sequenceNumber Optional sequence number (default 0).\n */\nexport const createExpiryFromDuration = (\n durationSecs: number,\n sequenceNumber: number = 0,\n): bigint => {\n const timestamp = Math.floor(Date.now() / 1000) + durationSecs\n return createExpiry(timestamp, sequenceNumber)\n}\n\n/**\n * Check if an expiry value has expired.\n *\n * @param expiry The expiry value to check.\n */\nexport const isExpired = (expiry: bigint): boolean => {\n const { timestamp } = parseExpiry(expiry)\n return timestamp < Math.floor(Date.now() / 1000)\n}\n"],"names":[],"mappings":";;AAGO,MAAM,aAAA,GAAgB,CAAC,GAAA,KAA8B;AAC1D,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA;AAC/B,EAAA,OAAO,MAAA,CAAO,KAAA,CAAM,SAAA,CAAU,GAAG,CAAC,CAAA;AACpC;AAEO,MAAM,YAAA,GAAe,CAAC,GAAA,KAAuB;AAClD,EAAA,IAAI,CAAC,GAAA,EAAK,OAAO,MAAM,IAAA;AACvB,EAAA,MAAM,MAAA,GAAS,GAAA;AACf,EAAA,OAAO,CAAC,CAAA,KAAiB,CAAA,CAAE,aAAA,KAAkB,MAAA;AAC/C;AAQO,MAAM,YAAA,GAAe,CAC1B,uBAAA,EACA,cAAA,GAAyB,CAAA,KACd;AACX,EAAA,IAAI,cAAA,GAAiB,CAAA,IAAK,cAAA,GAAiB,UAAA,EAAY;AACrD,IAAA,MAAM,IAAI,WAAW,qCAAqC,CAAA;AAAA,EAC5D;AACA,EAAA,OAAQ,MAAA,CAAO,uBAAuB,CAAA,IAAK,GAAA,GAAO,OAAO,cAAc,CAAA;AACzE;AAOO,MAAM,WAAA,GAAc,CACzB,MAAA,MAC6C;AAAA,EAC7C,SAAA,EAAW,MAAA,CAAO,MAAA,IAAU,GAAG,CAAA;AAAA,EAC/B,QAAA,EAAU,MAAA,CAAO,MAAA,GAAS,WAAW;AACvC,CAAA;AAQO,MAAM,wBAAA,GAA2B,CACtC,YAAA,EACA,cAAA,GAAyB,CAAA,KACd;AACX,EAAA,MAAM,YAAY,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,EAAI,GAAI,GAAI,CAAA,GAAI,YAAA;AAClD,EAAA,OAAO,YAAA,CAAa,WAAW,cAAc,CAAA;AAC/C;AAOO,MAAM,SAAA,GAAY,CAAC,MAAA,KAA4B;AACpD,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,WAAA,CAAY,MAAM,CAAA;AACxC,EAAA,OAAO,YAAY,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AACjD;;;;"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { Enum, SizedHex, HexString } from '@polkadot-api/substrate-bindings';
|
|
2
|
+
|
|
3
|
+
type Proof = Enum<{
|
|
4
|
+
sr25519: {
|
|
5
|
+
signature: SizedHex<64>;
|
|
6
|
+
signer: SizedHex<32>;
|
|
7
|
+
};
|
|
8
|
+
ed25519: {
|
|
9
|
+
signature: SizedHex<64>;
|
|
10
|
+
signer: SizedHex<32>;
|
|
11
|
+
};
|
|
12
|
+
ecdsa: {
|
|
13
|
+
signature: SizedHex<65>;
|
|
14
|
+
signer: SizedHex<33>;
|
|
15
|
+
};
|
|
16
|
+
onChain: {
|
|
17
|
+
who: SizedHex<32>;
|
|
18
|
+
blockHash: SizedHex<32>;
|
|
19
|
+
event: bigint;
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
22
|
+
type Statement = Partial<{
|
|
23
|
+
proof: Proof;
|
|
24
|
+
/** @deprecated Experimental feature, may be removed/changed in future releases */
|
|
25
|
+
decryptionKey: SizedHex<32>;
|
|
26
|
+
expiry: bigint;
|
|
27
|
+
channel: SizedHex<32>;
|
|
28
|
+
topics: Array<SizedHex<32>>;
|
|
29
|
+
data: Uint8Array;
|
|
30
|
+
}>;
|
|
31
|
+
type UnsignedStatement = Omit<Statement, "proof">;
|
|
32
|
+
type SignedStatement = UnsignedStatement & {
|
|
33
|
+
proof: Proof;
|
|
34
|
+
};
|
|
35
|
+
declare const statementCodec: any;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Filter for subscribing to statements with different topics.
|
|
39
|
+
*/
|
|
40
|
+
type TopicFilter = "any" | {
|
|
41
|
+
matchAll: Array<SizedHex<32>>;
|
|
42
|
+
} | {
|
|
43
|
+
matchAny: Array<SizedHex<32>>;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* An item returned by the statement subscription stream.
|
|
47
|
+
*/
|
|
48
|
+
type StatementEvent = {
|
|
49
|
+
event: "newStatements";
|
|
50
|
+
data: {
|
|
51
|
+
statements: HexString[];
|
|
52
|
+
remaining?: number;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
type SubmitNew = {
|
|
56
|
+
/**
|
|
57
|
+
* Statement was accepted as new.
|
|
58
|
+
*/
|
|
59
|
+
status: "new";
|
|
60
|
+
};
|
|
61
|
+
type SubmitKnown = {
|
|
62
|
+
/**
|
|
63
|
+
* Statement was already known.
|
|
64
|
+
*/
|
|
65
|
+
status: "known";
|
|
66
|
+
};
|
|
67
|
+
type SubmitKnownExpired = {
|
|
68
|
+
/**
|
|
69
|
+
* Statement was already known but has expired.
|
|
70
|
+
*/
|
|
71
|
+
status: "knownExpired";
|
|
72
|
+
};
|
|
73
|
+
type SubmitRejected = {
|
|
74
|
+
/**
|
|
75
|
+
* Statement was rejected because the store is full or expiry is too low.
|
|
76
|
+
*/
|
|
77
|
+
status: "rejected";
|
|
78
|
+
} & ({
|
|
79
|
+
/**
|
|
80
|
+
* Statement data exceeds the maximum allowed size for the account.
|
|
81
|
+
*/
|
|
82
|
+
reason: "dataTooLarge";
|
|
83
|
+
/**
|
|
84
|
+
* The size of the submitted statement data.
|
|
85
|
+
*/
|
|
86
|
+
submitted_size: number;
|
|
87
|
+
/**
|
|
88
|
+
* Still available data size for the account.
|
|
89
|
+
*/
|
|
90
|
+
available_size: number;
|
|
91
|
+
} | {
|
|
92
|
+
/**
|
|
93
|
+
* Attempting to replace a channel message with lower or equal expiry.
|
|
94
|
+
*/
|
|
95
|
+
reason: "channelPriorityTooLow";
|
|
96
|
+
/**
|
|
97
|
+
* The expiry of the submitted statement.
|
|
98
|
+
*/
|
|
99
|
+
submitted_expiry: bigint;
|
|
100
|
+
/**
|
|
101
|
+
* The minimum expiry of the existing channel message.
|
|
102
|
+
*/
|
|
103
|
+
min_expiry: bigint;
|
|
104
|
+
} | {
|
|
105
|
+
/**
|
|
106
|
+
* Account reached its statement limit and submitted expiry is too low
|
|
107
|
+
* to evict existing.
|
|
108
|
+
*/
|
|
109
|
+
reason: "accountFull";
|
|
110
|
+
/**
|
|
111
|
+
* The expiry of the submitted statement.
|
|
112
|
+
*/
|
|
113
|
+
submitted_expiry: bigint;
|
|
114
|
+
/**
|
|
115
|
+
* The minimum expiry of the existing statement.
|
|
116
|
+
*/
|
|
117
|
+
min_expiry: bigint;
|
|
118
|
+
} | {
|
|
119
|
+
/**
|
|
120
|
+
* The global statement store is full and cannot accept new statements.
|
|
121
|
+
*/
|
|
122
|
+
reason: "storeFull";
|
|
123
|
+
} | {
|
|
124
|
+
/**
|
|
125
|
+
* Account has no allowance set.
|
|
126
|
+
*/
|
|
127
|
+
reason: "noAllowance";
|
|
128
|
+
});
|
|
129
|
+
type SubmitInvalid = {
|
|
130
|
+
/**
|
|
131
|
+
* Statement failed validation.
|
|
132
|
+
*/
|
|
133
|
+
status: "invalid";
|
|
134
|
+
} & ({
|
|
135
|
+
/**
|
|
136
|
+
* Statement has no proof.
|
|
137
|
+
*/
|
|
138
|
+
reason: "noProof";
|
|
139
|
+
} | {
|
|
140
|
+
/**
|
|
141
|
+
* Proof validation failed.
|
|
142
|
+
*/
|
|
143
|
+
reason: "badProof";
|
|
144
|
+
} | {
|
|
145
|
+
/**
|
|
146
|
+
* Statement exceeds max allowed statement size.
|
|
147
|
+
*/
|
|
148
|
+
reason: "encodingTooLarge";
|
|
149
|
+
/**
|
|
150
|
+
* The size of the submitted statement encoding.
|
|
151
|
+
*/
|
|
152
|
+
submitted_size: number;
|
|
153
|
+
/**
|
|
154
|
+
* The maximum allowed size.
|
|
155
|
+
*/
|
|
156
|
+
max_size: number;
|
|
157
|
+
} | {
|
|
158
|
+
/**
|
|
159
|
+
* Statement has already expired. The expiry field is in the past.
|
|
160
|
+
*/
|
|
161
|
+
reason: "alreadyExpired";
|
|
162
|
+
});
|
|
163
|
+
type SubmitInternalError = {
|
|
164
|
+
/**
|
|
165
|
+
* Internal store error.
|
|
166
|
+
*/
|
|
167
|
+
status: "internalError";
|
|
168
|
+
/**
|
|
169
|
+
* Error message.
|
|
170
|
+
*/
|
|
171
|
+
error: string;
|
|
172
|
+
};
|
|
173
|
+
type SubmitResult = SubmitNew | SubmitKnown | SubmitKnownExpired | SubmitRejected | SubmitInvalid | SubmitInternalError;
|
|
174
|
+
|
|
175
|
+
type RequestFn = <Reply = any, Params extends Array<any> = any[]>(method: string, params: Params) => Promise<Reply>;
|
|
176
|
+
type SubscribeFn = <T = any, Params extends Array<any> = any[]>(method: string, params: Params, onMessage: (message: T) => void, onError: (error: Error) => void) => () => void;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Create statement sdk.
|
|
180
|
+
*
|
|
181
|
+
* @param {RequestFn} req Takes a req-res function, which accepts Statement RPC
|
|
182
|
+
* calls. This can be `client._request` (from
|
|
183
|
+
* `polkadot-api`) client, `client.request` (from
|
|
184
|
+
* `@polkadot-api/substrate-client`)
|
|
185
|
+
* or any other crafted by the consumer.
|
|
186
|
+
* @param {SubscribeFn} subscribe Takes a subscription function for RPC subscriptions.
|
|
187
|
+
* This can be `client._subscribe` (from `polkadot-api`)
|
|
188
|
+
* or any other crafted by the consumer.
|
|
189
|
+
*/
|
|
190
|
+
declare const createStatementSdk: (req: RequestFn, subscribe: SubscribeFn) => {
|
|
191
|
+
/**
|
|
192
|
+
* Submit a Statement to the store.
|
|
193
|
+
* It must be signed to be accepted.
|
|
194
|
+
*/
|
|
195
|
+
submit: (stmt: Statement) => Promise<SubmitResult>;
|
|
196
|
+
getStatements: (filter?: TopicFilter) => Promise<Statement[]>;
|
|
197
|
+
/**
|
|
198
|
+
* Subscribe to statements matching the given filter.
|
|
199
|
+
*
|
|
200
|
+
* Unlike `getStatements`, this maintains an active subscription and
|
|
201
|
+
* continues to receive new statements as they are added to the store.
|
|
202
|
+
*
|
|
203
|
+
* @param filter Topic filter for statements.
|
|
204
|
+
* @param onStatement Callback for each decoded statement.
|
|
205
|
+
* @param onError Callback for errors.
|
|
206
|
+
* @returns Unsubscribe function.
|
|
207
|
+
*/
|
|
208
|
+
subscribeStatements: (filter: TopicFilter, onStatement: (statement: Statement) => void, onError: (error: Error) => void) => (() => void);
|
|
209
|
+
/**
|
|
210
|
+
* Get broadcasts (statements with no decryptionKey) matching topics.
|
|
211
|
+
*
|
|
212
|
+
* @param topics Topics to match (all must be present).
|
|
213
|
+
*/
|
|
214
|
+
getBroadcasts: (topics?: Array<SizedHex<32>>) => Promise<Statement[]>;
|
|
215
|
+
/**
|
|
216
|
+
* Get posted statements (with decryptionKey) matching topics and destination.
|
|
217
|
+
*
|
|
218
|
+
* @param topics Topics to match (all must be present).
|
|
219
|
+
* @param dest Destination decryption key.
|
|
220
|
+
*/
|
|
221
|
+
getPosted: (topics: Array<SizedHex<32>>, dest: SizedHex<32>) => Promise<Statement[]>;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
declare const getStatementSigner: (publicKey: Uint8Array, type: "ed25519" | "sr25519" | "ecdsa", signFn: (payload: Uint8Array) => Promise<Uint8Array> | Uint8Array) => {
|
|
225
|
+
publicKey: Uint8Array<ArrayBufferLike>;
|
|
226
|
+
sign: (stmt: Statement) => Promise<SignedStatement>;
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
declare const stringToTopic: (str: string) => SizedHex<32>;
|
|
230
|
+
/**
|
|
231
|
+
* Create an expiry value from timestamp and sequence number.
|
|
232
|
+
*
|
|
233
|
+
* @param expirationTimestampSecs Expiration time in seconds since UNIX epoch.
|
|
234
|
+
* @param sequenceNumber Sequence number for ordering (0-4294967295).
|
|
235
|
+
*/
|
|
236
|
+
declare const createExpiry: (expirationTimestampSecs: number, sequenceNumber?: number) => bigint;
|
|
237
|
+
/**
|
|
238
|
+
* Parse an expiry value into its components.
|
|
239
|
+
*
|
|
240
|
+
* @param expiry The expiry value to parse.
|
|
241
|
+
*/
|
|
242
|
+
declare const parseExpiry: (expiry: bigint) => {
|
|
243
|
+
timestamp: number;
|
|
244
|
+
sequence: number;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Create an expiry value that expires after a given duration.
|
|
248
|
+
*
|
|
249
|
+
* @param durationSecs Duration in seconds from now.
|
|
250
|
+
* @param sequenceNumber Optional sequence number (default 0).
|
|
251
|
+
*/
|
|
252
|
+
declare const createExpiryFromDuration: (durationSecs: number, sequenceNumber?: number) => bigint;
|
|
253
|
+
/**
|
|
254
|
+
* Check if an expiry value has expired.
|
|
255
|
+
*
|
|
256
|
+
* @param expiry The expiry value to check.
|
|
257
|
+
*/
|
|
258
|
+
declare const isExpired: (expiry: bigint) => boolean;
|
|
259
|
+
|
|
260
|
+
export { createExpiry, createExpiryFromDuration, createStatementSdk, getStatementSigner, isExpired, parseExpiry, statementCodec, stringToTopic };
|
|
261
|
+
export type { Proof, RequestFn, SignedStatement, Statement, StatementEvent, SubmitResult, SubscribeFn, TopicFilter, UnsignedStatement };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var substrateBindings = require('@polkadot-api/substrate-bindings');
|
|
4
|
+
var utils = require('@polkadot-api/utils');
|
|
5
|
+
var polkadotApi = require('polkadot-api');
|
|
6
|
+
|
|
7
|
+
const sortIdxs = {
|
|
8
|
+
proof: 0,
|
|
9
|
+
decryptionKey: 1,
|
|
10
|
+
expiry: 2,
|
|
11
|
+
channel: 3,
|
|
12
|
+
topics: 4,
|
|
13
|
+
topic1: 4,
|
|
14
|
+
topic2: 5,
|
|
15
|
+
topic3: 6,
|
|
16
|
+
topic4: 7,
|
|
17
|
+
data: 8
|
|
18
|
+
};
|
|
19
|
+
const bin32 = substrateBindings.SizedBytes(32);
|
|
20
|
+
const bin64 = substrateBindings.SizedBytes(64);
|
|
21
|
+
const field = substrateBindings.Variant({
|
|
22
|
+
proof: substrateBindings.Variant({
|
|
23
|
+
sr25519: substrateBindings.Struct({ signature: bin64, signer: bin32 }),
|
|
24
|
+
ed25519: substrateBindings.Struct({ signature: bin64, signer: bin32 }),
|
|
25
|
+
ecdsa: substrateBindings.Struct({ signature: substrateBindings.SizedBytes(65), signer: substrateBindings.SizedBytes(33) }),
|
|
26
|
+
onChain: substrateBindings.Struct({ who: bin32, blockHash: bin32, event: substrateBindings.u64 })
|
|
27
|
+
}),
|
|
28
|
+
decryptionKey: bin32,
|
|
29
|
+
expiry: substrateBindings.u64,
|
|
30
|
+
channel: bin32,
|
|
31
|
+
topic1: bin32,
|
|
32
|
+
topic2: bin32,
|
|
33
|
+
topic3: bin32,
|
|
34
|
+
topic4: bin32,
|
|
35
|
+
data: substrateBindings.Bytes()
|
|
36
|
+
});
|
|
37
|
+
const innerStatement = substrateBindings.Vector(field);
|
|
38
|
+
const statementCodec = substrateBindings.enhanceCodec(
|
|
39
|
+
innerStatement,
|
|
40
|
+
(stmt) => {
|
|
41
|
+
const statement = [];
|
|
42
|
+
Object.keys(stmt).sort((a, b) => sortIdxs[a] - sortIdxs[b]).forEach((k) => {
|
|
43
|
+
if (k === "topics") {
|
|
44
|
+
if (stmt[k].length > 4)
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Max topics length is 4. Received ${stmt[k]?.length}`
|
|
47
|
+
);
|
|
48
|
+
stmt[k].forEach((v, i) => {
|
|
49
|
+
statement.push(substrateBindings.Enum(`topic${i + 1}`, v));
|
|
50
|
+
});
|
|
51
|
+
} else {
|
|
52
|
+
statement.push(substrateBindings.Enum(k, stmt[k]));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return statement;
|
|
56
|
+
},
|
|
57
|
+
(stmt) => {
|
|
58
|
+
const statement = {};
|
|
59
|
+
let maxTopicChecked = 0;
|
|
60
|
+
let maxIdx = -1;
|
|
61
|
+
stmt.forEach((v) => {
|
|
62
|
+
const idx = sortIdxs[v.type];
|
|
63
|
+
if (idx <= maxIdx) throw new Error("Unexpected entries order");
|
|
64
|
+
maxIdx = idx;
|
|
65
|
+
if (!v.type.startsWith("topic")) {
|
|
66
|
+
statement[v.type] = v.value;
|
|
67
|
+
} else if (v.type !== `topic${++maxTopicChecked}`) {
|
|
68
|
+
throw new Error(`Unexpected ${v.type}`);
|
|
69
|
+
} else {
|
|
70
|
+
statement.topics ?? (statement.topics = []);
|
|
71
|
+
statement.topics?.push(v.value);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return statement;
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const getApi = (req, subscribe) => ({
|
|
79
|
+
submit: (stmt) => req("statement_submit", [stmt]),
|
|
80
|
+
subscribeStatement: (topicFilter, onMessage, onError) => subscribe(
|
|
81
|
+
"statement_subscribeStatement",
|
|
82
|
+
[topicFilter],
|
|
83
|
+
onMessage,
|
|
84
|
+
onError
|
|
85
|
+
)
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const stringToTopic = (str) => {
|
|
89
|
+
const enc = substrateBindings.Binary.fromText(str);
|
|
90
|
+
return substrateBindings.Binary.toHex(substrateBindings.Blake2256(enc));
|
|
91
|
+
};
|
|
92
|
+
const filterDecKey = (key) => {
|
|
93
|
+
if (!key) return () => true;
|
|
94
|
+
const hexKey = key;
|
|
95
|
+
return (v) => v.decryptionKey === hexKey;
|
|
96
|
+
};
|
|
97
|
+
const createExpiry = (expirationTimestampSecs, sequenceNumber = 0) => {
|
|
98
|
+
if (sequenceNumber < 0 || sequenceNumber > 4294967295) {
|
|
99
|
+
throw new RangeError("sequenceNumber must be 0-4294967295");
|
|
100
|
+
}
|
|
101
|
+
return BigInt(expirationTimestampSecs) << 32n | BigInt(sequenceNumber);
|
|
102
|
+
};
|
|
103
|
+
const parseExpiry = (expiry) => ({
|
|
104
|
+
timestamp: Number(expiry >> 32n),
|
|
105
|
+
sequence: Number(expiry & 0xffffffffn)
|
|
106
|
+
});
|
|
107
|
+
const createExpiryFromDuration = (durationSecs, sequenceNumber = 0) => {
|
|
108
|
+
const timestamp = Math.floor(Date.now() / 1e3) + durationSecs;
|
|
109
|
+
return createExpiry(timestamp, sequenceNumber);
|
|
110
|
+
};
|
|
111
|
+
const isExpired = (expiry) => {
|
|
112
|
+
const { timestamp } = parseExpiry(expiry);
|
|
113
|
+
return timestamp < Math.floor(Date.now() / 1e3);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const ANY_FILTER = "any";
|
|
117
|
+
const createStatementSdk = (req, subscribe) => {
|
|
118
|
+
const api = getApi(req, subscribe);
|
|
119
|
+
const getStatements = (filter = ANY_FILTER) => new Promise((resolve, reject) => {
|
|
120
|
+
const statements = [];
|
|
121
|
+
const unsubscribe = api.subscribeStatement(
|
|
122
|
+
filter,
|
|
123
|
+
(event) => {
|
|
124
|
+
if (event.event === "newStatements") {
|
|
125
|
+
for (const encoded of event.data.statements) {
|
|
126
|
+
try {
|
|
127
|
+
statements.push(statementCodec.dec(encoded));
|
|
128
|
+
} catch (e) {
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (event.data.remaining === 0 || event.data.remaining === void 0) {
|
|
132
|
+
unsubscribe();
|
|
133
|
+
resolve(statements);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
(error) => {
|
|
138
|
+
unsubscribe();
|
|
139
|
+
reject(error);
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
return {
|
|
144
|
+
/**
|
|
145
|
+
* Submit a Statement to the store.
|
|
146
|
+
* It must be signed to be accepted.
|
|
147
|
+
*/
|
|
148
|
+
submit: (stmt) => api.submit(utils.toHex(statementCodec.enc(stmt))),
|
|
149
|
+
getStatements,
|
|
150
|
+
/**
|
|
151
|
+
* Subscribe to statements matching the given filter.
|
|
152
|
+
*
|
|
153
|
+
* Unlike `getStatements`, this maintains an active subscription and
|
|
154
|
+
* continues to receive new statements as they are added to the store.
|
|
155
|
+
*
|
|
156
|
+
* @param filter Topic filter for statements.
|
|
157
|
+
* @param onStatement Callback for each decoded statement.
|
|
158
|
+
* @param onError Callback for errors.
|
|
159
|
+
* @returns Unsubscribe function.
|
|
160
|
+
*/
|
|
161
|
+
subscribeStatements: (filter, onStatement, onError) => api.subscribeStatement(
|
|
162
|
+
filter,
|
|
163
|
+
(event) => {
|
|
164
|
+
if (event.event === "newStatements") {
|
|
165
|
+
for (const encoded of event.data.statements) {
|
|
166
|
+
try {
|
|
167
|
+
onStatement(statementCodec.dec(encoded));
|
|
168
|
+
} catch (e) {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
onError
|
|
174
|
+
),
|
|
175
|
+
/**
|
|
176
|
+
* Get broadcasts (statements with no decryptionKey) matching topics.
|
|
177
|
+
*
|
|
178
|
+
* @param topics Topics to match (all must be present).
|
|
179
|
+
*/
|
|
180
|
+
getBroadcasts: async (topics = []) => {
|
|
181
|
+
const filter = topics.length > 0 ? { matchAll: topics } : ANY_FILTER;
|
|
182
|
+
const statements = await getStatements(filter);
|
|
183
|
+
return statements.filter((stmt) => stmt.decryptionKey === void 0);
|
|
184
|
+
},
|
|
185
|
+
/**
|
|
186
|
+
* Get posted statements (with decryptionKey) matching topics and destination.
|
|
187
|
+
*
|
|
188
|
+
* @param topics Topics to match (all must be present).
|
|
189
|
+
* @param dest Destination decryption key.
|
|
190
|
+
*/
|
|
191
|
+
getPosted: async (topics, dest) => {
|
|
192
|
+
const filter = topics.length > 0 ? { matchAll: topics } : ANY_FILTER;
|
|
193
|
+
const statements = await getStatements(filter);
|
|
194
|
+
return statements.filter(filterDecKey(dest));
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const getStatementSigner = (publicKey, type, signFn) => ({
|
|
200
|
+
publicKey,
|
|
201
|
+
sign: async (stmt) => {
|
|
202
|
+
if (stmt.proof) throw new Error("Statement already signed");
|
|
203
|
+
const encoded = statementCodec.enc(stmt);
|
|
204
|
+
const compactLen = substrateBindings.compact.enc(substrateBindings.compact.dec(encoded)).length;
|
|
205
|
+
const signature = await signFn(encoded.slice(compactLen));
|
|
206
|
+
const result = statementCodec.dec(encoded);
|
|
207
|
+
result.proof = substrateBindings.Enum(type, {
|
|
208
|
+
signature: polkadotApi.Binary.toHex(signature),
|
|
209
|
+
// SizedHex<64> or SizedHex<65>
|
|
210
|
+
signer: polkadotApi.Binary.toHex(publicKey)
|
|
211
|
+
// SizedHex<32> or SizedHex<33>
|
|
212
|
+
});
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
exports.createExpiry = createExpiry;
|
|
218
|
+
exports.createExpiryFromDuration = createExpiryFromDuration;
|
|
219
|
+
exports.createStatementSdk = createStatementSdk;
|
|
220
|
+
exports.getStatementSigner = getStatementSigner;
|
|
221
|
+
exports.isExpired = isExpired;
|
|
222
|
+
exports.parseExpiry = parseExpiry;
|
|
223
|
+
exports.statementCodec = statementCodec;
|
|
224
|
+
exports.stringToTopic = stringToTopic;
|
|
225
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/codec/codec.ts","../src/api.ts","../src/utils.ts","../src/statement-sdk.ts","../src/signer.ts"],"sourcesContent":["import {\n Bytes,\n CodecType,\n enhanceCodec,\n Enum,\n HexString,\n SizedBytes,\n SizedHex,\n Struct,\n u64,\n Variant,\n Vector,\n} from \"@polkadot-api/substrate-bindings\"\n\nexport type Proof = Enum<{\n sr25519: { signature: SizedHex<64>; signer: SizedHex<32> }\n ed25519: { signature: SizedHex<64>; signer: SizedHex<32> }\n ecdsa: { signature: SizedHex<65>; signer: SizedHex<33> }\n onChain: {\n who: SizedHex<32>\n blockHash: SizedHex<32>\n event: bigint\n }\n}>\n\nexport type Statement = Partial<{\n proof: Proof\n /** @deprecated Experimental feature, may be removed/changed in future releases */\n decryptionKey: SizedHex<32>\n expiry: bigint\n channel: SizedHex<32>\n topics: Array<SizedHex<32>>\n data: Uint8Array\n}>\n\nconst sortIdxs = {\n proof: 0,\n decryptionKey: 1,\n expiry: 2,\n channel: 3,\n topics: 4,\n topic1: 4,\n topic2: 5,\n topic3: 6,\n topic4: 7,\n data: 8,\n}\n\nexport type UnsignedStatement = Omit<Statement, \"proof\">\nexport type SignedStatement = UnsignedStatement & { proof: Proof }\n\nconst bin32 = SizedBytes(32)\nconst bin64 = SizedBytes(64)\n\nconst field = Variant({\n proof: Variant({\n sr25519: Struct({ signature: bin64, signer: bin32 }),\n ed25519: Struct({ signature: bin64, signer: bin32 }),\n ecdsa: Struct({ signature: SizedBytes(65), signer: SizedBytes(33) }),\n onChain: Struct({ who: bin32, blockHash: bin32, event: u64 }),\n }),\n decryptionKey: bin32,\n expiry: u64,\n channel: bin32,\n topic1: bin32,\n topic2: bin32,\n topic3: bin32,\n topic4: bin32,\n data: Bytes(),\n})\nconst innerStatement = Vector(field)\n\nexport const statementCodec = enhanceCodec<\n CodecType<typeof innerStatement>,\n Statement\n>(\n innerStatement,\n (stmt) => {\n const statement: CodecType<typeof innerStatement> = []\n ;(Object.keys(stmt) as Array<keyof Statement>)\n .sort((a, b) => sortIdxs[a] - sortIdxs[b])\n .forEach((k) => {\n if (k === \"topics\") {\n if (stmt[k]!.length > 4)\n throw new Error(\n `Max topics length is 4. Received ${stmt[k]?.length}`,\n )\n stmt[k]!.forEach((v, i) => {\n statement.push(Enum(`topic${i + 1}` as `topic${1 | 2 | 3 | 4}`, v))\n })\n } else {\n statement.push(Enum(k, stmt[k]!))\n }\n })\n return statement\n },\n (stmt) => {\n const statement: Statement = {}\n let maxTopicChecked = 0\n let maxIdx = -1\n stmt.forEach((v) => {\n // ensure order and no repetition\n const idx = sortIdxs[v.type]\n if (idx <= maxIdx) throw new Error(\"Unexpected entries order\")\n maxIdx = idx\n\n if (!v.type.startsWith(\"topic\")) {\n ;(statement as any)[v.type] = v.value\n } else if (v.type !== `topic${++maxTopicChecked}`) {\n throw new Error(`Unexpected ${v.type}`)\n } else {\n statement.topics ??= []\n statement.topics?.push(v.value as HexString)\n }\n })\n return statement\n },\n)\n","import { HexString } from \"@polkadot-api/substrate-bindings\"\nimport { SubmitResult, TopicFilter, StatementEvent } from \"./types\"\n\nexport type RequestFn = <Reply = any, Params extends Array<any> = any[]>(\n method: string,\n params: Params,\n) => Promise<Reply>\n\nexport type SubscribeFn = <T = any, Params extends Array<any> = any[]>(\n method: string,\n params: Params,\n onMessage: (message: T) => void,\n onError: (error: Error) => void,\n) => () => void\n\nexport const getApi = (req: RequestFn, subscribe: SubscribeFn) => ({\n submit: (stmt: HexString) =>\n req<SubmitResult, [HexString]>(\"statement_submit\", [stmt]),\n\n subscribeStatement: (\n topicFilter: TopicFilter,\n onMessage: (event: StatementEvent) => void,\n onError: (error: Error) => void,\n ) =>\n subscribe<StatementEvent, [TopicFilter]>(\n \"statement_subscribeStatement\",\n [topicFilter],\n onMessage,\n onError,\n ),\n})\n","import { Binary, Blake2256, SizedHex } from \"@polkadot-api/substrate-bindings\"\nimport { Statement } from \"./codec\"\n\nexport const stringToTopic = (str: string): SizedHex<32> => {\n const enc = Binary.fromText(str) // Returns Uint8Array directly\n return Binary.toHex(Blake2256(enc)) as SizedHex<32> // SizedHex is now SizedHex (string)\n}\n\nexport const filterDecKey = (key?: SizedHex<32>) => {\n if (!key) return () => true\n const hexKey = key // Already a hex string (SizedHex)\n return (v: Statement) => v.decryptionKey === hexKey\n}\n\n/**\n * Create an expiry value from timestamp and sequence number.\n *\n * @param expirationTimestampSecs Expiration time in seconds since UNIX epoch.\n * @param sequenceNumber Sequence number for ordering (0-4294967295).\n */\nexport const createExpiry = (\n expirationTimestampSecs: number,\n sequenceNumber: number = 0,\n): bigint => {\n if (sequenceNumber < 0 || sequenceNumber > 0xffffffff) {\n throw new RangeError(\"sequenceNumber must be 0-4294967295\")\n }\n return (BigInt(expirationTimestampSecs) << 32n) | BigInt(sequenceNumber)\n}\n\n/**\n * Parse an expiry value into its components.\n *\n * @param expiry The expiry value to parse.\n */\nexport const parseExpiry = (\n expiry: bigint,\n): { timestamp: number; sequence: number } => ({\n timestamp: Number(expiry >> 32n),\n sequence: Number(expiry & 0xffffffffn),\n})\n\n/**\n * Create an expiry value that expires after a given duration.\n *\n * @param durationSecs Duration in seconds from now.\n * @param sequenceNumber Optional sequence number (default 0).\n */\nexport const createExpiryFromDuration = (\n durationSecs: number,\n sequenceNumber: number = 0,\n): bigint => {\n const timestamp = Math.floor(Date.now() / 1000) + durationSecs\n return createExpiry(timestamp, sequenceNumber)\n}\n\n/**\n * Check if an expiry value has expired.\n *\n * @param expiry The expiry value to check.\n */\nexport const isExpired = (expiry: bigint): boolean => {\n const { timestamp } = parseExpiry(expiry)\n return timestamp < Math.floor(Date.now() / 1000)\n}\n","import { SizedHex } from \"@polkadot-api/substrate-bindings\"\nimport { Statement, statementCodec } from \"./codec\"\nimport { toHex } from \"@polkadot-api/utils\"\nimport { getApi, RequestFn, SubscribeFn } from \"./api\"\nimport { filterDecKey } from \"./utils\"\nimport { SubmitResult, TopicFilter, StatementEvent } from \"./types\"\n\nconst ANY_FILTER: TopicFilter = \"any\"\n\n/**\n * Create statement sdk.\n *\n * @param {RequestFn} req Takes a req-res function, which accepts Statement RPC\n * calls. This can be `client._request` (from\n * `polkadot-api`) client, `client.request` (from\n * `@polkadot-api/substrate-client`)\n * or any other crafted by the consumer.\n * @param {SubscribeFn} subscribe Takes a subscription function for RPC subscriptions.\n * This can be `client._subscribe` (from `polkadot-api`)\n * or any other crafted by the consumer.\n */\nexport const createStatementSdk = (req: RequestFn, subscribe: SubscribeFn) => {\n const api = getApi(req, subscribe)\n\n /**\n * Get statements from store matching the given filter.\n *\n * This method subscribes to the statement store, collects all existing\n * statements matching the filter, then unsubscribes and returns them.\n *\n * @param filter Topic filter for statements. Defaults to matching all.\n */\n const getStatements = (\n filter: TopicFilter = ANY_FILTER,\n ): Promise<Statement[]> =>\n new Promise((resolve, reject) => {\n const statements: Statement[] = []\n\n const unsubscribe = api.subscribeStatement(\n filter,\n (event: StatementEvent) => {\n if (event.event === \"newStatements\") {\n for (const encoded of event.data.statements) {\n try {\n statements.push(statementCodec.dec(encoded))\n } catch (e) {\n // Skip malformed statements\n }\n }\n\n // Initial dump complete when remaining is 0 or undefined\n if (\n event.data.remaining === 0 ||\n event.data.remaining === undefined\n ) {\n unsubscribe()\n resolve(statements)\n }\n }\n },\n (error: Error) => {\n unsubscribe()\n reject(error)\n },\n )\n })\n\n return {\n /**\n * Submit a Statement to the store.\n * It must be signed to be accepted.\n */\n submit: (stmt: Statement): Promise<SubmitResult> =>\n api.submit(toHex(statementCodec.enc(stmt))),\n\n getStatements,\n\n /**\n * Subscribe to statements matching the given filter.\n *\n * Unlike `getStatements`, this maintains an active subscription and\n * continues to receive new statements as they are added to the store.\n *\n * @param filter Topic filter for statements.\n * @param onStatement Callback for each decoded statement.\n * @param onError Callback for errors.\n * @returns Unsubscribe function.\n */\n subscribeStatements: (\n filter: TopicFilter,\n onStatement: (statement: Statement) => void,\n onError: (error: Error) => void,\n ): (() => void) =>\n api.subscribeStatement(\n filter,\n (event: StatementEvent) => {\n if (event.event === \"newStatements\") {\n for (const encoded of event.data.statements) {\n try {\n onStatement(statementCodec.dec(encoded))\n } catch (e) {\n // Skip malformed statements\n }\n }\n }\n },\n onError,\n ),\n\n /**\n * Get broadcasts (statements with no decryptionKey) matching topics.\n *\n * @param topics Topics to match (all must be present).\n */\n getBroadcasts: async (\n topics: Array<SizedHex<32>> = [],\n ): Promise<Statement[]> => {\n const filter: TopicFilter =\n topics.length > 0 ? { matchAll: topics } : ANY_FILTER\n const statements = await getStatements(filter)\n return statements.filter((stmt) => stmt.decryptionKey === undefined)\n },\n\n /**\n * Get posted statements (with decryptionKey) matching topics and destination.\n *\n * @param topics Topics to match (all must be present).\n * @param dest Destination decryption key.\n */\n getPosted: async (\n topics: Array<SizedHex<32>>,\n dest: SizedHex<32>,\n ): Promise<Statement[]> => {\n const filter: TopicFilter =\n topics.length > 0 ? { matchAll: topics } : ANY_FILTER\n const statements = await getStatements(filter)\n return statements.filter(filterDecKey(dest))\n },\n }\n}\n","import { compact, Enum } from \"@polkadot-api/substrate-bindings\"\nimport { Binary } from \"polkadot-api\"\nimport { SignedStatement, Statement, statementCodec } from \"./codec\"\n\nexport const getStatementSigner = (\n publicKey: Uint8Array,\n type: \"ed25519\" | \"sr25519\" | \"ecdsa\",\n signFn: (payload: Uint8Array) => Promise<Uint8Array> | Uint8Array,\n) => ({\n publicKey,\n sign: async (stmt: Statement): Promise<SignedStatement> => {\n if (stmt.proof) throw new Error(\"Statement already signed\")\n const encoded = statementCodec.enc(stmt)\n const compactLen = compact.enc(compact.dec(encoded)).length\n const signature = await signFn(encoded.slice(compactLen))\n const result = statementCodec.dec(encoded)\n result.proof = Enum(type, {\n signature: Binary.toHex(signature) as any, // SizedHex<64> or SizedHex<65>\n signer: Binary.toHex(publicKey) as any, // SizedHex<32> or SizedHex<33>\n })\n return result as SignedStatement\n },\n})\n"],"names":["SizedBytes","Variant","Struct","u64","Bytes","Vector","enhanceCodec","Enum","Binary","Blake2256","toHex","compact"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@novasamatech/sdk-statement",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"author": "Carlo Sala (https://github.com/carlosala)",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/novasamatech/papi-sdks.git"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"node": {
|
|
13
|
+
"production": {
|
|
14
|
+
"import": "./dist/esm/index.mjs",
|
|
15
|
+
"require": "./dist/min/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"import": "./dist/esm/index.mjs",
|
|
19
|
+
"require": "./dist/index.js",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"module": "./dist/esm/index.mjs",
|
|
23
|
+
"import": "./dist/esm/index.mjs",
|
|
24
|
+
"require": "./dist/index.js",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
},
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"module": "./dist/esm/index.mjs",
|
|
31
|
+
"browser": "./dist/esm/index.mjs",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"files": [
|
|
34
|
+
"dist"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc --noEmit && rollup -c ../../rollup.config.js",
|
|
38
|
+
"lint": "prettier --check README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
|
39
|
+
"format": "prettier --write README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
|
40
|
+
"test": "vitest"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@polkadot-api/substrate-bindings": "0.19.0",
|
|
45
|
+
"@polkadot-api/utils": "^0.3.0",
|
|
46
|
+
"polkadot-api": "^2.0.0-rc.2"
|
|
47
|
+
}
|
|
48
|
+
}
|