@novasamatech/product-sdk 0.7.8 → 0.7.9-1
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 +26 -22
- package/dist/accounts.d.ts +54 -3
- package/dist/accounts.js +101 -42
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/injectWeb3.d.ts +68 -2
- package/dist/injectWeb3.js +27 -8
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -211,15 +211,12 @@ subscription.unsubscribe();
|
|
|
211
211
|
The Accounts Provider allows you to access product accounts and create signers for signing transactions.
|
|
212
212
|
|
|
213
213
|
```ts
|
|
214
|
-
import {
|
|
214
|
+
import { accounts } from '@novasamatech/product-sdk';
|
|
215
215
|
import type { ProductAccount } from '@novasamatech/product-sdk';
|
|
216
216
|
|
|
217
|
-
// Create accounts provider instance
|
|
218
|
-
const accountsProvider = createAccountsProvider();
|
|
219
|
-
|
|
220
217
|
// Get the user's primary DotNS username (RFC-0014)
|
|
221
218
|
// — prompts for permission on first call
|
|
222
|
-
const userIdResult = await
|
|
219
|
+
const userIdResult = await accounts.getUserId();
|
|
223
220
|
|
|
224
221
|
if (userIdResult.isOk()) {
|
|
225
222
|
const { primaryUsername } = userIdResult.value;
|
|
@@ -234,7 +231,7 @@ if (userIdResult.isOk()) {
|
|
|
234
231
|
}
|
|
235
232
|
|
|
236
233
|
// Request login — triggers host sign-in UI; reason is shown to the user
|
|
237
|
-
const loginResult = await
|
|
234
|
+
const loginResult = await accounts.requestLogin('Sign in to access your account');
|
|
238
235
|
|
|
239
236
|
if (loginResult.isOk()) {
|
|
240
237
|
const outcome = loginResult.value; // 'success' | 'alreadyConnected' | 'rejected'
|
|
@@ -246,7 +243,7 @@ if (loginResult.isOk()) {
|
|
|
246
243
|
}
|
|
247
244
|
|
|
248
245
|
// Get a product account by DotNS identifier and derivation index
|
|
249
|
-
const accountResult = await
|
|
246
|
+
const accountResult = await accounts.getProductAccount('product.dot', 0);
|
|
250
247
|
|
|
251
248
|
if (accountResult.isOk()) {
|
|
252
249
|
const account: ProductAccount = accountResult.value;
|
|
@@ -254,42 +251,49 @@ if (accountResult.isOk()) {
|
|
|
254
251
|
}
|
|
255
252
|
|
|
256
253
|
// Get account alias
|
|
257
|
-
const aliasResult = await
|
|
254
|
+
const aliasResult = await accounts.getProductAccountAlias('product.dot', 0);
|
|
258
255
|
|
|
259
256
|
if (aliasResult.isOk()) {
|
|
260
257
|
console.log('Alias:', aliasResult.value);
|
|
261
258
|
}
|
|
262
259
|
|
|
263
260
|
// Get legacy accounts (external wallets)
|
|
264
|
-
const legacyAccountsResult = await
|
|
261
|
+
const legacyAccountsResult = await accounts.getLegacyAccounts();
|
|
265
262
|
|
|
266
263
|
if (legacyAccountsResult.isOk()) {
|
|
267
264
|
console.log('Legacy accounts:', legacyAccountsResult.value);
|
|
268
265
|
}
|
|
269
266
|
|
|
270
267
|
// Subscribe to account connection status changes
|
|
271
|
-
const unsubscribe =
|
|
268
|
+
const unsubscribe = accounts.subscribeAccountConnectionStatus((status) => {
|
|
272
269
|
// status: 'connected' | 'disconnected'
|
|
273
270
|
console.log('Account connection status:', status);
|
|
274
271
|
});
|
|
275
272
|
|
|
276
|
-
// Create a signer for a product account (for use with PAPI)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
derivationIndex: 0,
|
|
280
|
-
publicKey: new Uint8Array([/* ... */])
|
|
281
|
-
};
|
|
282
|
-
const signer = accountsProvider.getProductAccountSigner(account);
|
|
273
|
+
// Create a signer for a product account (for use with PAPI).
|
|
274
|
+
// Resolve the account first, then hand it to the signer factory.
|
|
275
|
+
const productAccountResult = await accounts.getProductAccount('product.dot', 0);
|
|
283
276
|
|
|
284
|
-
|
|
285
|
-
const
|
|
277
|
+
if (productAccountResult.isOk()) {
|
|
278
|
+
const productSigner = accounts.getProductAccountSigner(productAccountResult.value);
|
|
279
|
+
const signedTx = await tx.signAndSubmit(productSigner);
|
|
280
|
+
}
|
|
286
281
|
|
|
287
|
-
//
|
|
282
|
+
// Create a signer for a legacy account.
|
|
283
|
+
// Fetch the legacy account list, pick one, then pass it to the signer factory.
|
|
284
|
+
const legacyAccountsResult = await accounts.getLegacyAccounts();
|
|
288
285
|
|
|
289
|
-
|
|
290
|
-
const
|
|
286
|
+
if (legacyAccountsResult.isOk()) {
|
|
287
|
+
const [legacyAccount] = legacyAccountsResult.value;
|
|
288
|
+
if (legacyAccount) {
|
|
289
|
+
const legacySigner = accounts.getLegacyAccountSigner(legacyAccount);
|
|
290
|
+
const signedTx = await tx.signAndSubmit(legacySigner);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
291
293
|
```
|
|
292
294
|
|
|
295
|
+
> If you need a non-default transport (e.g. for tests or multi-host setups), use `createAccountsProvider(transport)` to build your own instance with the same API.
|
|
296
|
+
|
|
293
297
|
### Local Storage
|
|
294
298
|
|
|
295
299
|
The Local Storage module provides a way to persist data in the host application's storage.
|
package/dist/accounts.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import type { AccountConnectionStatus as AccountConnectionStatusCodec, CodecType, Subscription, Transport } from '@novasamatech/host-api';
|
|
1
|
+
import type { AccountConnectionStatus as AccountConnectionStatusCodec, CodecType, LegacyAccount as LegacyAccountCodec, ProductAccountId as ProductAccountIdCodec, Subscription, Transport } from '@novasamatech/host-api';
|
|
2
2
|
import { RingLocation } from '@novasamatech/host-api';
|
|
3
3
|
import type { PolkadotSigner } from 'polkadot-api';
|
|
4
|
+
export type ProductAccountId = CodecType<typeof ProductAccountIdCodec>;
|
|
4
5
|
export type ProductAccount = {
|
|
5
6
|
dotNsIdentifier: string;
|
|
6
7
|
derivationIndex: number;
|
|
7
8
|
publicKey: Uint8Array;
|
|
8
9
|
};
|
|
10
|
+
export type LegacyAccount = CodecType<typeof LegacyAccountCodec>;
|
|
9
11
|
export type AccountConnectionStatus = CodecType<typeof AccountConnectionStatusCodec>;
|
|
10
12
|
export declare const createAccountsProvider: (transport?: Transport) => {
|
|
11
13
|
getUserId(): import("neverthrow").ResultAsync<{
|
|
@@ -18,6 +20,8 @@ export declare const createAccountsProvider: (transport?: Transport) => {
|
|
|
18
20
|
}, "LoginErr::Unknown">>;
|
|
19
21
|
getProductAccount(dotNsIdentifier: string, derivationIndex?: number): import("neverthrow").ResultAsync<{
|
|
20
22
|
publicKey: Uint8Array<ArrayBufferLike>;
|
|
23
|
+
dotNsIdentifier: string;
|
|
24
|
+
derivationIndex: number;
|
|
21
25
|
}, import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::Rejected"> | import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::DomainNotValid"> | import("@novasamatech/scale").CodecError<{
|
|
22
26
|
reason: string;
|
|
23
27
|
}, "RequestCredentialsErr::Unknown">>;
|
|
@@ -36,7 +40,54 @@ export declare const createAccountsProvider: (transport?: Transport) => {
|
|
|
36
40
|
createRingVRFProof(dotNsIdentifier: string, derivationIndex: number | undefined, location: CodecType<typeof RingLocation>, message: Uint8Array): import("neverthrow").ResultAsync<Uint8Array<ArrayBufferLike>, import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
37
41
|
reason: string;
|
|
38
42
|
}, "CreateProofErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::RingNotFound">>;
|
|
39
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Builds a `PolkadotSigner` that delegates to the host via `host_create_transaction`.
|
|
45
|
+
*
|
|
46
|
+
* The factory is async because `PolkadotSigner.publicKey` must be a synchronous
|
|
47
|
+
* `Uint8Array` on the returned object — it is fetched up front via `host_account_get`.
|
|
48
|
+
*/
|
|
49
|
+
getProductAccountSigner(account: ProductAccount, signerType?: "signPayload" | "createTransaction"): PolkadotSigner;
|
|
40
50
|
subscribeAccountConnectionStatus(callback: (status: AccountConnectionStatus) => void): Subscription<void>;
|
|
41
|
-
getLegacyAccountSigner(account:
|
|
51
|
+
getLegacyAccountSigner(account: LegacyAccount): PolkadotSigner;
|
|
52
|
+
};
|
|
53
|
+
export declare const accounts: {
|
|
54
|
+
getUserId(): import("neverthrow").ResultAsync<{
|
|
55
|
+
primaryUsername: string;
|
|
56
|
+
}, import("@novasamatech/scale").CodecError<undefined, "GetUserIdErr::NotConnected"> | import("@novasamatech/scale").CodecError<{
|
|
57
|
+
reason: string;
|
|
58
|
+
}, "GetUserIdErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "GetUserIdErr::PermissionDenied">>;
|
|
59
|
+
requestLogin(reason?: string): import("neverthrow").ResultAsync<"success" | "alreadyConnected" | "rejected", import("@novasamatech/scale").CodecError<{
|
|
60
|
+
reason: string;
|
|
61
|
+
}, "LoginErr::Unknown">>;
|
|
62
|
+
getProductAccount(dotNsIdentifier: string, derivationIndex?: number): import("neverthrow").ResultAsync<{
|
|
63
|
+
publicKey: Uint8Array<ArrayBufferLike>;
|
|
64
|
+
dotNsIdentifier: string;
|
|
65
|
+
derivationIndex: number;
|
|
66
|
+
}, import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::Rejected"> | import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::DomainNotValid"> | import("@novasamatech/scale").CodecError<{
|
|
67
|
+
reason: string;
|
|
68
|
+
}, "RequestCredentialsErr::Unknown">>;
|
|
69
|
+
getProductAccountAlias(dotNsIdentifier: string, derivationIndex?: number): import("neverthrow").ResultAsync<{
|
|
70
|
+
context: Uint8Array<ArrayBufferLike>;
|
|
71
|
+
alias: Uint8Array<ArrayBufferLike>;
|
|
72
|
+
}, import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::Rejected"> | import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::DomainNotValid"> | import("@novasamatech/scale").CodecError<{
|
|
73
|
+
reason: string;
|
|
74
|
+
}, "RequestCredentialsErr::Unknown">>;
|
|
75
|
+
getLegacyAccounts(): import("neverthrow").ResultAsync<{
|
|
76
|
+
publicKey: Uint8Array<ArrayBufferLike>;
|
|
77
|
+
name: string | undefined;
|
|
78
|
+
}[], import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::Rejected"> | import("@novasamatech/scale").CodecError<undefined, "RequestCredentialsErr::DomainNotValid"> | import("@novasamatech/scale").CodecError<{
|
|
79
|
+
reason: string;
|
|
80
|
+
}, "RequestCredentialsErr::Unknown">>;
|
|
81
|
+
createRingVRFProof(dotNsIdentifier: string, derivationIndex: number | undefined, location: CodecType<typeof RingLocation>, message: Uint8Array): import("neverthrow").ResultAsync<Uint8Array<ArrayBufferLike>, import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
82
|
+
reason: string;
|
|
83
|
+
}, "CreateProofErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::RingNotFound">>;
|
|
84
|
+
/**
|
|
85
|
+
* Builds a `PolkadotSigner` that delegates to the host via `host_create_transaction`.
|
|
86
|
+
*
|
|
87
|
+
* The factory is async because `PolkadotSigner.publicKey` must be a synchronous
|
|
88
|
+
* `Uint8Array` on the returned object — it is fetched up front via `host_account_get`.
|
|
89
|
+
*/
|
|
90
|
+
getProductAccountSigner(account: ProductAccount, signerType?: "signPayload" | "createTransaction"): PolkadotSigner;
|
|
91
|
+
subscribeAccountConnectionStatus(callback: (status: AccountConnectionStatus) => void): Subscription<void>;
|
|
92
|
+
getLegacyAccountSigner(account: LegacyAccount): PolkadotSigner;
|
|
42
93
|
};
|
package/dist/accounts.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CreateProofErr, GetUserIdErr, LoginErr, RequestCredentialsErr, RingLocation, SigningPayload, SigningPayloadWithoutAccount, SigningRawPayload, SigningRawPayloadWithoutAccount, assertEnumVariant, createHostApi, enumValue, fromHex, isEnumVariant, toHex, } from '@novasamatech/host-api';
|
|
2
|
+
import { decAnyMetadata, unifyMetadata } from '@polkadot-api/substrate-bindings';
|
|
2
3
|
import { err, ok } from 'neverthrow';
|
|
3
4
|
import { getPolkadotSignerFromPjs } from 'polkadot-api/pjs-signer';
|
|
4
5
|
import { sandboxTransport } from './sandboxTransport.js';
|
|
@@ -36,7 +37,11 @@ export const createAccountsProvider = (transport = sandboxTransport) => {
|
|
|
36
37
|
.mapErr(e => e.value)
|
|
37
38
|
.andThen(response => {
|
|
38
39
|
if (isEnumVariant(response, 'v1')) {
|
|
39
|
-
return ok(
|
|
40
|
+
return ok({
|
|
41
|
+
publicKey: response.value.publicKey,
|
|
42
|
+
dotNsIdentifier,
|
|
43
|
+
derivationIndex,
|
|
44
|
+
});
|
|
40
45
|
}
|
|
41
46
|
// @ts-expect-error response.tag is never here
|
|
42
47
|
return err(new RequestCredentialsErr.Unknown({ reason: `Unsupported response version ${response.tag}` }));
|
|
@@ -78,50 +83,103 @@ export const createAccountsProvider = (transport = sandboxTransport) => {
|
|
|
78
83
|
return err(new CreateProofErr.Unknown({ reason: `Unsupported response version ${response.tag}` }));
|
|
79
84
|
});
|
|
80
85
|
},
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Builds a `PolkadotSigner` that delegates to the host via `host_create_transaction`.
|
|
88
|
+
*
|
|
89
|
+
* The factory is async because `PolkadotSigner.publicKey` must be a synchronous
|
|
90
|
+
* `Uint8Array` on the returned object — it is fetched up front via `host_account_get`.
|
|
91
|
+
*/
|
|
92
|
+
getProductAccountSigner(account, signerType = 'signPayload') {
|
|
93
|
+
const hostApi = createHostApi(transport);
|
|
94
|
+
const productAccountId = [account.dotNsIdentifier, account.derivationIndex];
|
|
95
|
+
/**
|
|
96
|
+
* @deprecated added for backward compatibility
|
|
97
|
+
*/
|
|
98
|
+
if (signerType === 'signPayload') {
|
|
99
|
+
return getPolkadotSignerFromPjs(toHex(account.publicKey), async (payload) => {
|
|
100
|
+
const codecPayload = {
|
|
101
|
+
account: [account.dotNsIdentifier, account.derivationIndex],
|
|
102
|
+
payload: buildSigningPayloadFields(payload),
|
|
94
103
|
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
104
|
+
const response = await hostApi.signPayload(enumValue('v1', codecPayload));
|
|
105
|
+
return response.match(response => {
|
|
106
|
+
assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
107
|
+
return {
|
|
108
|
+
id: 0,
|
|
109
|
+
signature: response.value.signature,
|
|
110
|
+
signedTransaction: response.value.signedTransaction,
|
|
111
|
+
};
|
|
112
|
+
}, err => {
|
|
113
|
+
assertEnumVariant(err, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
114
|
+
throw err.value;
|
|
115
|
+
});
|
|
116
|
+
}, async (raw) => {
|
|
117
|
+
const payload = {
|
|
118
|
+
account: [account.dotNsIdentifier, account.derivationIndex],
|
|
119
|
+
payload: raw.type === 'bytes'
|
|
120
|
+
? {
|
|
121
|
+
tag: 'Bytes',
|
|
122
|
+
value: fromHex(asHex(raw.data)),
|
|
123
|
+
}
|
|
124
|
+
: {
|
|
125
|
+
tag: 'Payload',
|
|
126
|
+
value: raw.data,
|
|
127
|
+
},
|
|
119
128
|
};
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
129
|
+
const response = await hostApi.signRaw(enumValue('v1', payload));
|
|
130
|
+
return response.match(response => {
|
|
131
|
+
assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
132
|
+
return {
|
|
133
|
+
id: 0,
|
|
134
|
+
signature: response.value.signature,
|
|
135
|
+
signedTransaction: response.value.signedTransaction,
|
|
136
|
+
};
|
|
137
|
+
}, err => {
|
|
138
|
+
assertEnumVariant(err, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
139
|
+
throw err.value;
|
|
140
|
+
});
|
|
123
141
|
});
|
|
124
|
-
}
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
publicKey: account.publicKey,
|
|
145
|
+
async signTx(callData, signedExtensions, metadata) {
|
|
146
|
+
const decMeta = unifyMetadata(decAnyMetadata(metadata));
|
|
147
|
+
const { version: versions } = decMeta.extrinsic;
|
|
148
|
+
const latestVersion = versions.reduce((acc, v) => Math.max(acc, v), 0);
|
|
149
|
+
const txExtVersion = latestVersion === 4 ? 0 : latestVersion;
|
|
150
|
+
const txPayload = {
|
|
151
|
+
signer: productAccountId,
|
|
152
|
+
callData,
|
|
153
|
+
extensions: Object.values(signedExtensions).map(({ identifier, value, additionalSigned }) => ({
|
|
154
|
+
id: identifier,
|
|
155
|
+
extra: value,
|
|
156
|
+
additionalSigned: additionalSigned,
|
|
157
|
+
})),
|
|
158
|
+
txExtVersion,
|
|
159
|
+
};
|
|
160
|
+
const response = await hostApi.createTransaction(enumValue('v1', txPayload));
|
|
161
|
+
return response.match(response => {
|
|
162
|
+
assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
163
|
+
return response.value;
|
|
164
|
+
}, err => {
|
|
165
|
+
assertEnumVariant(err, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
166
|
+
throw err.value;
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
async signBytes(data) {
|
|
170
|
+
const response = await hostApi.signRaw(enumValue('v1', {
|
|
171
|
+
account: productAccountId,
|
|
172
|
+
payload: { tag: 'Bytes', value: data },
|
|
173
|
+
}));
|
|
174
|
+
return response.match(response => {
|
|
175
|
+
assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
176
|
+
return fromHex(response.value.signature);
|
|
177
|
+
}, err => {
|
|
178
|
+
assertEnumVariant(err, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
179
|
+
throw err.value;
|
|
180
|
+
});
|
|
181
|
+
},
|
|
182
|
+
};
|
|
125
183
|
},
|
|
126
184
|
subscribeAccountConnectionStatus(callback) {
|
|
127
185
|
const subscriber = hostApi.accountConnectionStatusSubscribe(enumValue('v1', undefined), status => {
|
|
@@ -173,6 +231,7 @@ export const createAccountsProvider = (transport = sandboxTransport) => {
|
|
|
173
231
|
},
|
|
174
232
|
};
|
|
175
233
|
};
|
|
234
|
+
export const accounts = createAccountsProvider();
|
|
176
235
|
function asHex(v) {
|
|
177
236
|
if (v.startsWith('0x'))
|
|
178
237
|
return v;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ export type { ChatBotRegistrationResult, ChatCustomMessageRenderer, ChatCustomMe
|
|
|
8
8
|
export { createProductChatManager, matchChatCustomRenderers } from './chat.js';
|
|
9
9
|
export type { ProductAccountId, SignedStatement, Statement, StatementTopicFilter, StatementsPage, Topic, } from './statementStore.js';
|
|
10
10
|
export { createStatementStore } from './statementStore.js';
|
|
11
|
-
export type { AccountConnectionStatus, ProductAccount } from './accounts.js';
|
|
12
|
-
export { createAccountsProvider } from './accounts.js';
|
|
11
|
+
export type { AccountConnectionStatus, LegacyAccount, ProductAccount } from './accounts.js';
|
|
12
|
+
export { accounts, createAccountsProvider } from './accounts.js';
|
|
13
13
|
export type { ThemeMode } from './theme.js';
|
|
14
14
|
export { createThemeProvider } from './theme.js';
|
|
15
15
|
export { createLocalStorage, hostLocalStorage } from './localStorage.js';
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ export { createLegacyExtensionEnableFactory, injectSpektrExtension } from './inj
|
|
|
6
6
|
export { createPapiProvider } from './papiProvider.js';
|
|
7
7
|
export { createProductChatManager, matchChatCustomRenderers } from './chat.js';
|
|
8
8
|
export { createStatementStore } from './statementStore.js';
|
|
9
|
-
export { createAccountsProvider } from './accounts.js';
|
|
9
|
+
export { accounts, createAccountsProvider } from './accounts.js';
|
|
10
10
|
export { createThemeProvider } from './theme.js';
|
|
11
11
|
export { createLocalStorage, hostLocalStorage } from './localStorage.js';
|
|
12
12
|
export { createPreimageManager, preimageManager } from './preimage.js';
|
package/dist/injectWeb3.d.ts
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { HexString, Transport } from '@novasamatech/host-api';
|
|
2
2
|
import type { InjectedAccounts } from '@polkadot/extension-inject/types';
|
|
3
3
|
import type { SignerPayloadJSON, SignerPayloadRaw, SignerResult } from '@polkadot/types/types/extrinsic';
|
|
4
|
+
/**
|
|
5
|
+
* expected interface derived from specification
|
|
6
|
+
*/
|
|
7
|
+
export interface TxPayloadV1 {
|
|
8
|
+
/** Payload version. MUST be 1. */
|
|
9
|
+
version: 1;
|
|
10
|
+
/**
|
|
11
|
+
* Signer selection hint. Allows the implementer to identify which private-key / scheme to use.
|
|
12
|
+
* - Use a wallet-defined handle (e.g., address/SS58, account-name, etc). This identifier
|
|
13
|
+
* was previously made available to the consumer.
|
|
14
|
+
* - Set `null` to let the implementer pick the signer (or if the signer is implied).
|
|
15
|
+
*/
|
|
16
|
+
signer: string | null;
|
|
17
|
+
/**
|
|
18
|
+
* SCALE-encoded Call (module indicator + function indicator + params).
|
|
19
|
+
*/
|
|
20
|
+
callData: HexString;
|
|
21
|
+
/**
|
|
22
|
+
* Transaction extensions supplied by the caller (order irrelevant).
|
|
23
|
+
* The consumer SHOULD provide every extension that is relevant to them.
|
|
24
|
+
* The implementer MAY infer missing ones.
|
|
25
|
+
*/
|
|
26
|
+
extensions: Array<{
|
|
27
|
+
/** Identifier as defined in metadata (e.g., "CheckSpecVersion", "ChargeAssetTxPayment"). */
|
|
28
|
+
id: string;
|
|
29
|
+
/**
|
|
30
|
+
* Explicit "extra" to sign (goes into the extrinsic body).
|
|
31
|
+
* SCALE-encoded per the extension's "extra" type as defined in the metadata.
|
|
32
|
+
*/
|
|
33
|
+
extra: HexString;
|
|
34
|
+
/**
|
|
35
|
+
* "Implicit" data to sign (known by the chain, not included into the extrinsic body).
|
|
36
|
+
* SCALE-encoded per the extension's "additionalSigned" type as defined in the metadata.
|
|
37
|
+
*/
|
|
38
|
+
additionalSigned: HexString;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Transaction Extension Version.
|
|
42
|
+
* - For Extrinsic V4 MUST be 0.
|
|
43
|
+
* - For Extrinsic V5, set to any version supported by the runtime.
|
|
44
|
+
* The implementer:
|
|
45
|
+
* - MUST use this field to determine the required extensions for creating the extrinsic.
|
|
46
|
+
* - MAY use this field to infer missing extensions that the implementer could know how to handle.
|
|
47
|
+
*/
|
|
48
|
+
txExtVersion: number;
|
|
49
|
+
/**
|
|
50
|
+
* Context needed for decoding, display, and (optionally) inferring certain extensions.
|
|
51
|
+
*/
|
|
52
|
+
context: {
|
|
53
|
+
/**
|
|
54
|
+
* RuntimeMetadataPrefixed blob (SCALE), starting with ASCII "meta" magic (`0x6d657461`),
|
|
55
|
+
* then a metadata version (V14+). For V5+ versioned extensions, MUST provide V16+.
|
|
56
|
+
*/
|
|
57
|
+
metadata: HexString;
|
|
58
|
+
/**
|
|
59
|
+
* Native token display info (used by some implementers), also needed to compute
|
|
60
|
+
* the `CheckMetadataHash` value.
|
|
61
|
+
*/
|
|
62
|
+
tokenSymbol: string;
|
|
63
|
+
tokenDecimals: number;
|
|
64
|
+
/**
|
|
65
|
+
* Highest known block number to aid mortality UX.
|
|
66
|
+
*/
|
|
67
|
+
bestBlockHeight: number;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
4
70
|
interface Signer {
|
|
5
71
|
/**
|
|
6
72
|
* @description signs an extrinsic payload from a serialized form
|
|
@@ -13,7 +79,7 @@ interface Signer {
|
|
|
13
79
|
/**
|
|
14
80
|
* @description signs a transaction according to https://github.com/polkadot-js/api/issues/6213
|
|
15
81
|
*/
|
|
16
|
-
createTransaction?: (payload:
|
|
82
|
+
createTransaction?: (payload: TxPayloadV1) => Promise<HexString>;
|
|
17
83
|
}
|
|
18
84
|
interface Injected {
|
|
19
85
|
accounts: InjectedAccounts;
|
package/dist/injectWeb3.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { assertEnumVariant, createHostApi, enumValue, fromHex, toHex } from '@novasamatech/host-api';
|
|
2
2
|
import { injectExtension } from '@polkadot/extension-inject';
|
|
3
3
|
import { AccountId } from 'polkadot-api';
|
|
4
|
+
import { createAccountsProvider } from './accounts.js';
|
|
4
5
|
import { SpektrExtensionName, Version } from './constants.js';
|
|
5
6
|
import { sandboxTransport } from './sandboxTransport.js';
|
|
6
7
|
const UNSUPPORTED_VERSION_ERROR = 'Unsupported message version';
|
|
@@ -8,21 +9,22 @@ export async function createLegacyExtensionEnableFactory(transport) {
|
|
|
8
9
|
const ready = await transport.isReady();
|
|
9
10
|
if (!ready)
|
|
10
11
|
return null;
|
|
12
|
+
const accountsManager = createAccountsProvider(transport);
|
|
11
13
|
const hostApi = createHostApi(transport);
|
|
12
14
|
const accountId = AccountId();
|
|
13
15
|
async function enable() {
|
|
14
16
|
async function getAccounts() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return response.
|
|
17
|
+
return await accountsManager
|
|
18
|
+
.getLegacyAccounts()
|
|
19
|
+
.map(response => {
|
|
20
|
+
return response.map(account => ({
|
|
19
21
|
name: account.name,
|
|
20
22
|
address: accountId.dec(account.publicKey),
|
|
21
23
|
type: 'sr25519',
|
|
22
24
|
}));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
throw
|
|
25
|
+
})
|
|
26
|
+
.match(x => x, x => {
|
|
27
|
+
throw x;
|
|
26
28
|
});
|
|
27
29
|
}
|
|
28
30
|
return {
|
|
@@ -99,7 +101,24 @@ export async function createLegacyExtensionEnableFactory(transport) {
|
|
|
99
101
|
});
|
|
100
102
|
},
|
|
101
103
|
async createTransaction(payload) {
|
|
102
|
-
|
|
104
|
+
if (payload.version !== 1) {
|
|
105
|
+
throw new Error(`Signer support only v1 transaction, got version = ${payload.version}`);
|
|
106
|
+
}
|
|
107
|
+
const { signer } = payload;
|
|
108
|
+
if (!signer) {
|
|
109
|
+
throw new Error("Signer can't route transaction to the right account without signer hint.");
|
|
110
|
+
}
|
|
111
|
+
const possibleAccountId = accountId.enc(signer);
|
|
112
|
+
const response = await hostApi.createTransactionWithLegacyAccount(enumValue('v1', {
|
|
113
|
+
signer: possibleAccountId,
|
|
114
|
+
callData: fromHex(payload.callData),
|
|
115
|
+
txExtVersion: payload.txExtVersion,
|
|
116
|
+
extensions: payload.extensions.map(e => ({
|
|
117
|
+
id: e.id,
|
|
118
|
+
additionalSigned: fromHex(e.additionalSigned),
|
|
119
|
+
extra: fromHex(e.extra),
|
|
120
|
+
})),
|
|
121
|
+
}));
|
|
103
122
|
return response.match(response => {
|
|
104
123
|
assertEnumVariant(response, 'v1', UNSUPPORTED_VERSION_ERROR);
|
|
105
124
|
return toHex(response.value);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novasamatech/product-sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.9-1",
|
|
5
5
|
"description": "Polkadot product SDK: integrate and run your product inside Polkadot browser.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@polkadot/extension-inject": "^0.63.1",
|
|
29
29
|
"@polkadot-api/json-rpc-provider-proxy": "^0.4.0",
|
|
30
|
-
"@
|
|
30
|
+
"@polkadot-api/substrate-bindings": "^0.20.2",
|
|
31
|
+
"@novasamatech/host-api": "0.7.9-1",
|
|
31
32
|
"polkadot-api": ">=2",
|
|
32
33
|
"neverthrow": "^8.2.0"
|
|
33
34
|
},
|