@usebutr/polkadot 0.1.3 → 1.0.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/dist/index.d.ts +12 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -124
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ChainBase, PlatformDiscoverer, PolkadotAdapter, WalletAdapter, WalletCapabilities } from "@usebutr/core";
|
|
2
1
|
import { WalletStandardWallet, WalletStandardWalletAccount } from "@usebutr/wallet-standard-shared";
|
|
2
|
+
import { ChainBase, PlatformDiscoverer, PolkadotAdapter, WalletAdapter, WalletCapabilities } from "@usebutr/core";
|
|
3
3
|
//#region src/chains.d.ts
|
|
4
4
|
declare const POLKADOT_CHAINS: {
|
|
5
5
|
readonly kusama: {
|
|
@@ -39,15 +39,15 @@ type WalletStandardPolkadotCapabilityInput = {
|
|
|
39
39
|
};
|
|
40
40
|
/**
|
|
41
41
|
* injectedWeb3 capability profile. The injected `signer.signRaw` always
|
|
42
|
-
* supports message signing
|
|
43
|
-
*
|
|
44
|
-
*
|
|
42
|
+
* supports message signing and `accounts.subscribe` always supports events,
|
|
43
|
+
* so both are unconditional. The chain count comes from butr's own registry
|
|
44
|
+
* because injectedWeb3 wallets advertise no chains of their own.
|
|
45
45
|
*/
|
|
46
46
|
declare const resolveInjectedPolkadotCapabilities: () => WalletCapabilities;
|
|
47
47
|
/**
|
|
48
|
-
* Wallet Standard `polkadot:*` capability mapping.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
48
|
+
* Wallet Standard `polkadot:*` feature → butr capability mapping. No
|
|
49
|
+
* standalone `signTransaction`: building an extrinsic needs chain metadata
|
|
50
|
+
* butr doesn't fetch, so transaction signing goes through `getSigner()`.
|
|
51
51
|
*/
|
|
52
52
|
declare const resolveWalletStandardPolkadotCapabilities: (input: WalletStandardPolkadotCapabilityInput) => WalletCapabilities;
|
|
53
53
|
//#endregion
|
|
@@ -157,9 +157,11 @@ type PolkadotSignMessageFeature = {
|
|
|
157
157
|
* sendTx/getBalance/getTransactionReceipt are placeholders; transaction
|
|
158
158
|
* signing goes through `getSigner()` (returns the Wallet Standard wallet).
|
|
159
159
|
*/
|
|
160
|
-
declare const buildPolkadotWalletStandardAdapter: (wallet: WalletStandardWallet,
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
declare const buildPolkadotWalletStandardAdapter: (wallet: WalletStandardWallet,
|
|
161
|
+
/** Optional. Called with a function that pushes a synthetic
|
|
162
|
+
* `disconnected` event to all current subscribers. The discovery
|
|
163
|
+
* layer invokes it on Wallet Standard `unregister`. */
|
|
164
|
+
registerDisconnector?: (emit: () => void) => void) => WalletAdapter | null;
|
|
163
165
|
/**
|
|
164
166
|
* Subscribe to Wallet Standard announcements and emit adapters for
|
|
165
167
|
* wallets advertising `polkadot:*` features (Talisman, SubWallet). Used
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/chains.ts","../src/capabilities.ts","../src/injected/injected-web3.ts","../src/injected/adapter.ts","../src/injected/index.ts","../src/wallet-standard-types.ts","../src/wallet-standard-adapter.ts","../src/
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/chains.ts","../src/capabilities.ts","../src/injected/injected-web3.ts","../src/injected/adapter.ts","../src/injected/index.ts","../src/wallet-standard-types.ts","../src/wallet-standard-adapter.ts","../src/discoverer.ts","../src/signer-augmentation.ts"],"mappings":";;;cAMM;;;;;;;;;;;;;;;;;;;;;;;;;;cA2BA,sBAAsB,cAAc;;;KC5BrC;EACH;EACA;IACE;IACA;;;;;;;;;cAUE,2CAA0C;;;;;;cAe1C,4CACJ,OAAO,0CACN;;;;;;;;;;;;KC1BE;EACH;EACA;EACA;EACA;;;;KAKG;EACH,WAAW;IACT;IACA;IACA;QACI;IAAU;IAAY;;;;KAIzB;EACH;IACE,WAAW,QAAQ,cAAc;IACjC,aAAa,KAAK,UAAU,cAAc;;EAE5C,QAAQ;;;KAIL;EACH,SAAS,mBAAmB,QAAQ;EACpC;;KAGG;EACH,eAAe,eAAe;;;;;;;;KCpB3B;EACH;EACA,WAAW;EACX;;;;;;;;;;;cAoCI,+BACJ,uBACA,qBACA,UAAU,2BACT;;;KC7CE;;;EAGH,SAAS;;EAET,SAAS;;;;;;;;;;;cAcL,mCACJ,YAAY,SAAS,wBACrB,UAAS;;;KCnCN;EACH,SAAS;EACT,SAAS;;KAGN;EACH,WAAW;EACX,gBAAgB;;KAGb;EACH,cAAc,OAAO,6BAA6B,QAAQ;;;;;;;;;;;cCMtD,qCACJ,QAAQ,sBAIR;;;;AAAA,wBAAwB,8BACvB;;;;;;;cAuDG,yCACJ,YAAY,SAAS;;;;;;;;;;;;;;cCtEjB,oBAAoB;;;;;;;;;;;;;;YCAd;IACR,UAAU,uBAAuB"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { buildWalletCapabilities, createWalletStandardCore, discoverWalletStandard, getFeature, slugify } from "@usebutr/wallet-standard-shared";
|
|
2
|
+
import { bytesToHexPrefixed as bytesToHex, hexToBytes, sanitizeIcon } from "@usebutr/core";
|
|
3
3
|
|
|
4
4
|
//#region src/chains.ts
|
|
5
5
|
const POLKADOT_CHAINS = {
|
|
@@ -34,38 +34,30 @@ const POLKADOT_CHAINS_LIST = Object.values(POLKADOT_CHAINS);
|
|
|
34
34
|
//#region src/capabilities.ts
|
|
35
35
|
/**
|
|
36
36
|
* injectedWeb3 capability profile. The injected `signer.signRaw` always
|
|
37
|
-
* supports message signing
|
|
38
|
-
*
|
|
39
|
-
*
|
|
37
|
+
* supports message signing and `accounts.subscribe` always supports events,
|
|
38
|
+
* so both are unconditional. The chain count comes from butr's own registry
|
|
39
|
+
* because injectedWeb3 wallets advertise no chains of their own.
|
|
40
40
|
*/
|
|
41
|
-
const resolveInjectedPolkadotCapabilities = () => ({
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
requestAccounts: false,
|
|
41
|
+
const resolveInjectedPolkadotCapabilities = () => buildWalletCapabilities({
|
|
42
|
+
chainCount: POLKADOT_CHAINS_LIST.length,
|
|
43
|
+
events: true,
|
|
45
44
|
sendTransaction: false,
|
|
46
45
|
signIn: false,
|
|
47
46
|
signMessage: true,
|
|
48
|
-
signTransaction: false
|
|
49
|
-
subscribe: true,
|
|
50
|
-
switchAccount: false,
|
|
51
|
-
switchChain: true
|
|
47
|
+
signTransaction: false
|
|
52
48
|
});
|
|
53
49
|
/**
|
|
54
|
-
* Wallet Standard `polkadot:*` capability mapping.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
50
|
+
* Wallet Standard `polkadot:*` feature → butr capability mapping. No
|
|
51
|
+
* standalone `signTransaction`: building an extrinsic needs chain metadata
|
|
52
|
+
* butr doesn't fetch, so transaction signing goes through `getSigner()`.
|
|
57
53
|
*/
|
|
58
|
-
const resolveWalletStandardPolkadotCapabilities = (input) => ({
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
requestAccounts: false,
|
|
54
|
+
const resolveWalletStandardPolkadotCapabilities = (input) => buildWalletCapabilities({
|
|
55
|
+
chainCount: input.chainCount,
|
|
56
|
+
events: input.features.events,
|
|
62
57
|
sendTransaction: false,
|
|
63
58
|
signIn: false,
|
|
64
59
|
signMessage: input.features.signMessage,
|
|
65
|
-
signTransaction: false
|
|
66
|
-
subscribe: input.features.events,
|
|
67
|
-
switchAccount: false,
|
|
68
|
-
switchChain: input.chainCount > 1
|
|
60
|
+
signTransaction: false
|
|
69
61
|
});
|
|
70
62
|
|
|
71
63
|
//#endregion
|
|
@@ -79,8 +71,8 @@ const resolveWalletStandardPolkadotCapabilities = (input) => ({
|
|
|
79
71
|
* `getSigner()`. Both discovery channels (injectedWeb3 + Wallet Standard)
|
|
80
72
|
* share these so the invariant lives in one place.
|
|
81
73
|
*/
|
|
82
|
-
const POLKADOT_SEND_TX_HINT = "Polkadot sendTx is unsupported
|
|
83
|
-
const POLKADOT_SEND_TX_TO_CHAIN_HINT = "Polkadot sendTxToChain is unsupported
|
|
74
|
+
const POLKADOT_SEND_TX_HINT = "Polkadot sendTx is unsupported: use getSigner() with polkadot-api to build and submit extrinsics";
|
|
75
|
+
const POLKADOT_SEND_TX_TO_CHAIN_HINT = "Polkadot sendTxToChain is unsupported: use getSigner() with polkadot-api to build and submit extrinsics";
|
|
84
76
|
const noRpcBalance = () => Promise.resolve({
|
|
85
77
|
decimals: 0,
|
|
86
78
|
formatted: "0",
|
|
@@ -284,13 +276,6 @@ const discoverInjectedPolkadotAdapters = (onAdapter, options = {}) => {
|
|
|
284
276
|
//#region src/wallet-standard-adapter.ts
|
|
285
277
|
const POLKADOT_PREFIX = "polkadot:";
|
|
286
278
|
const slugify$1 = (name) => slugify("polkadot", name);
|
|
287
|
-
const pickPolkadotChain = (wallet) => wallet.chains.find((c) => c.startsWith(POLKADOT_PREFIX)) ?? null;
|
|
288
|
-
const buildChain = (chainId, walletName) => ({
|
|
289
|
-
id: chainId,
|
|
290
|
-
name: walletName,
|
|
291
|
-
namespace: "polkadot",
|
|
292
|
-
reference: chainId.slice(9)
|
|
293
|
-
});
|
|
294
279
|
/**
|
|
295
280
|
* Adapt a Wallet Standard wallet advertising `polkadot:*` features into a
|
|
296
281
|
* butr `WalletAdapter`. Returns `null` for wallets that don't advertise a
|
|
@@ -299,120 +284,46 @@ const buildChain = (chainId, walletName) => ({
|
|
|
299
284
|
* signing goes through `getSigner()` (returns the Wallet Standard wallet).
|
|
300
285
|
*/
|
|
301
286
|
const buildPolkadotWalletStandardAdapter = (wallet, registerDisconnector) => {
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const notifyAccountChanged = () => {
|
|
313
|
-
if (wallet.accounts.length === 0) return;
|
|
314
|
-
const chain = currentChain();
|
|
315
|
-
const built = wallet.accounts.map((a) => buildAccount(a.address, chain));
|
|
316
|
-
const first = built[0];
|
|
317
|
-
if (first === void 0) return;
|
|
318
|
-
for (const listener of listeners) listener({
|
|
319
|
-
account: first,
|
|
320
|
-
accounts: built,
|
|
321
|
-
type: "accountChanged"
|
|
322
|
-
});
|
|
323
|
-
};
|
|
324
|
-
registerDisconnector?.(() => {
|
|
325
|
-
for (const listener of listeners) listener({ type: "disconnected" });
|
|
287
|
+
const core = createWalletStandardCore({
|
|
288
|
+
chainPrefix: POLKADOT_PREFIX,
|
|
289
|
+
id: slugify$1(wallet.name),
|
|
290
|
+
label: "Polkadot",
|
|
291
|
+
namespace: "polkadot",
|
|
292
|
+
platform: "Polkadot",
|
|
293
|
+
preferredChainIds: [],
|
|
294
|
+
registerDisconnector,
|
|
295
|
+
trackChainChanges: false,
|
|
296
|
+
wallet
|
|
326
297
|
});
|
|
298
|
+
if (core === null) return null;
|
|
299
|
+
const signMessage = getFeature(wallet, "polkadot:signMessage");
|
|
327
300
|
return {
|
|
301
|
+
...core,
|
|
328
302
|
capabilities: resolveWalletStandardPolkadotCapabilities({
|
|
329
|
-
chainCount:
|
|
303
|
+
chainCount: core.chainCount,
|
|
330
304
|
features: {
|
|
331
|
-
events:
|
|
305
|
+
events: core.hasEvents,
|
|
332
306
|
signMessage: Boolean(signMessage)
|
|
333
307
|
}
|
|
334
308
|
}),
|
|
335
309
|
chainPlatform: "polkadot",
|
|
336
|
-
async connect(opts) {
|
|
337
|
-
await connect.connect(opts?.silent === true ? { silent: true } : void 0);
|
|
338
|
-
},
|
|
339
|
-
async disconnect() {
|
|
340
|
-
if (disconnect !== void 0) try {
|
|
341
|
-
await disconnect.disconnect();
|
|
342
|
-
} catch (error) {
|
|
343
|
-
logWarn("[butr] Polkadot Wallet Standard disconnect threw:", error);
|
|
344
|
-
}
|
|
345
|
-
},
|
|
346
|
-
getAccount: () => {
|
|
347
|
-
const address = pickFirstAddress(wallet.accounts);
|
|
348
|
-
return Promise.resolve(address === null ? null : buildAccount(address, currentChain()));
|
|
349
|
-
},
|
|
350
|
-
getAccounts: () => {
|
|
351
|
-
const chain = currentChain();
|
|
352
|
-
return Promise.resolve(wallet.accounts.map((a) => buildAccount(a.address, chain)));
|
|
353
|
-
},
|
|
354
310
|
getBalance: noRpcBalance,
|
|
355
|
-
getSigner: () => Promise.resolve(wallet),
|
|
356
311
|
getTransactionReceipt: noRpcTransactionReceipt,
|
|
357
|
-
icon: sanitizeIcon(wallet.icon),
|
|
358
|
-
id: slugify$1(wallet.name),
|
|
359
|
-
name: wallet.name,
|
|
360
312
|
sendTx: noRpcSendTx,
|
|
361
313
|
sendTxToChain: noRpcSendTxToChain,
|
|
362
314
|
async signMessage(msg, account) {
|
|
363
315
|
if (signMessage === void 0) throw new Error(`Wallet ${wallet.name} does not advertise polkadot:signMessage`);
|
|
364
|
-
const wsAccount = account ? pickAccountByAddress(wallet.accounts, account.walletAddress) : wallet.accounts[0];
|
|
365
|
-
if (wsAccount === void 0) throw new Error("No connected account");
|
|
366
316
|
const output = await signMessage.signMessage({
|
|
367
|
-
account:
|
|
317
|
+
account: core.resolveAccount(account),
|
|
368
318
|
message: msg
|
|
369
319
|
});
|
|
370
320
|
return {
|
|
371
321
|
signature: output.signature,
|
|
372
322
|
signedMessage: output.signedMessage ?? msg
|
|
373
323
|
};
|
|
374
|
-
},
|
|
375
|
-
subscribe(listener) {
|
|
376
|
-
listeners.add(listener);
|
|
377
|
-
let unsubWallet = null;
|
|
378
|
-
if (events !== void 0) {
|
|
379
|
-
const unsub = events.on("change", (changes) => {
|
|
380
|
-
if (changes.accounts !== void 0) {
|
|
381
|
-
if (changes.accounts.length === 0) {
|
|
382
|
-
listener({ type: "disconnected" });
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
const chain = currentChain();
|
|
386
|
-
const built = changes.accounts.map((a) => buildAccount(a.address, chain));
|
|
387
|
-
const first = built[0];
|
|
388
|
-
if (first !== void 0) listener({
|
|
389
|
-
account: first,
|
|
390
|
-
accounts: built,
|
|
391
|
-
type: "accountChanged"
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
unsubWallet = () => {
|
|
396
|
-
unsub();
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
return () => {
|
|
400
|
-
listeners.delete(listener);
|
|
401
|
-
unsubWallet?.();
|
|
402
|
-
};
|
|
403
|
-
},
|
|
404
|
-
switchChain: (target) => {
|
|
405
|
-
if (target.namespace !== "polkadot") throw new Error(`Polkadot adapter received non-Polkadot chain "${target.id}". Pass a chain with namespace "polkadot".`);
|
|
406
|
-
if (!wallet.chains.includes(target.id)) throw new Error(`Wallet ${wallet.name} does not advertise chain "${target.id}". Available: ${wallet.chains.join(", ")}`);
|
|
407
|
-
currentChainId = target.id;
|
|
408
|
-
notifyAccountChanged();
|
|
409
|
-
return Promise.resolve();
|
|
410
324
|
}
|
|
411
325
|
};
|
|
412
326
|
};
|
|
413
|
-
|
|
414
|
-
//#endregion
|
|
415
|
-
//#region src/wallet-standard.ts
|
|
416
327
|
/**
|
|
417
328
|
* Subscribe to Wallet Standard announcements and emit adapters for
|
|
418
329
|
* wallets advertising `polkadot:*` features (Talisman, SubWallet). Used
|
|
@@ -439,7 +350,6 @@ const polkadotDiscoverer = {
|
|
|
439
350
|
if (opts.hasAnyPrimaryAdapter()) return () => void 0;
|
|
440
351
|
return discoverPolkadotWalletStandardAdapters(onAdapter);
|
|
441
352
|
} },
|
|
442
|
-
platform: "polkadot",
|
|
443
353
|
subscribe: discoverInjectedPolkadotAdapters
|
|
444
354
|
};
|
|
445
355
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["slugify","kitSlugify"],"sources":["../src/chains.ts","../src/capabilities.ts","../src/no-rpc.ts","../src/injected/icon.ts","../src/injected/injected-web3.ts","../src/injected/adapter.ts","../src/injected/index.ts","../src/wallet-standard-adapter.ts","../src/wallet-standard.ts","../src/discoverer.ts"],"sourcesContent":["import type { ChainBase } from \"@usebutr/core\";\n\n// CAIP-2 for Polkadot is `polkadot:{first-32-hex-of-genesis-hash}`.\n// injectedWeb3 doesn't advertise chains (accounts are chain-agnostic\n// across Substrate), so this registry is butr-authored. Wallet Standard\n// polkadot wallets advertise these same CAIP-2 ids.\nconst POLKADOT_CHAINS = {\n kusama: {\n id: \"polkadot:b0a8d493285c2df73290dfb7e61f870f\",\n name: \"Kusama\",\n namespace: \"polkadot\",\n reference: \"b0a8d493285c2df73290dfb7e61f870f\",\n },\n paseo: {\n id: \"polkadot:77afd6190f1554ad45fd0d31aee62aac\",\n name: \"Paseo\",\n namespace: \"polkadot\",\n reference: \"77afd6190f1554ad45fd0d31aee62aac\",\n },\n polkadot: {\n id: \"polkadot:91b171bb158e2d3848fa23a9f1c25182\",\n name: \"Polkadot\",\n namespace: \"polkadot\",\n reference: \"91b171bb158e2d3848fa23a9f1c25182\",\n },\n westend: {\n id: \"polkadot:e143f23803ac50e8f6f8e62695d1ce9e\",\n name: \"Westend\",\n namespace: \"polkadot\",\n reference: \"e143f23803ac50e8f6f8e62695d1ce9e\",\n },\n} as const satisfies Record<string, ChainBase>;\n\nconst POLKADOT_CHAINS_LIST: ReadonlyArray<ChainBase> = Object.values(POLKADOT_CHAINS);\n\nexport { POLKADOT_CHAINS, POLKADOT_CHAINS_LIST };\n","import type { WalletCapabilities } from \"@usebutr/core\";\n\ntype WalletStandardPolkadotCapabilityInput = {\n chainCount: number;\n features: {\n events: boolean;\n signMessage: boolean;\n };\n};\n\n/**\n * injectedWeb3 capability profile. The injected `signer.signRaw` always\n * supports message signing; `accounts.subscribe` always supports events;\n * butr authors the chain list (4 chains) so local switchChain is always\n * available.\n */\nconst resolveInjectedPolkadotCapabilities = (): WalletCapabilities => ({\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: false,\n sendTransaction: false,\n signIn: false,\n signMessage: true,\n signTransaction: false,\n subscribe: true,\n switchAccount: false,\n switchChain: true,\n});\n\n/**\n * Wallet Standard `polkadot:*` capability mapping. Mirrors the Sui/SVM\n * resolvers: features come from what the wallet advertises; switchChain\n * follows chainCount (local re-routing among advertised chains).\n */\nconst resolveWalletStandardPolkadotCapabilities = (\n input: WalletStandardPolkadotCapabilityInput,\n): WalletCapabilities => ({\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: false,\n sendTransaction: false,\n signIn: false,\n signMessage: input.features.signMessage,\n signTransaction: false,\n subscribe: input.features.events,\n switchAccount: false,\n switchChain: input.chainCount > 1,\n});\n\nexport type { WalletStandardPolkadotCapabilityInput };\nexport { resolveInjectedPolkadotCapabilities, resolveWalletStandardPolkadotCapabilities };\n","import type { Balance } from \"@usebutr/core\";\n\n/**\n * butr ships no RPC on Polkadot: building/broadcasting an extrinsic and\n * reading on-chain state both need chain metadata. Balance and receipt\n * reads return neutral placeholders (gated behind\n * `capabilities.getBalance` / `getTransactionReceipt === false`);\n * transaction submission rejects with a hint to drive polkadot-api via\n * `getSigner()`. Both discovery channels (injectedWeb3 + Wallet Standard)\n * share these so the invariant lives in one place.\n */\nconst POLKADOT_SEND_TX_HINT =\n \"Polkadot sendTx is unsupported — use getSigner() with polkadot-api to build and submit extrinsics\";\nconst POLKADOT_SEND_TX_TO_CHAIN_HINT =\n \"Polkadot sendTxToChain is unsupported — use getSigner() with polkadot-api to build and submit extrinsics\";\n\nconst noRpcBalance = (): Promise<Balance> =>\n Promise.resolve({ decimals: 0, formatted: \"0\", symbol: \"\", value: 0n });\n\nconst noRpcTransactionReceipt = (): Promise<{ status: \"Success\" | \"Error\" | \"Pending\" }> =>\n Promise.resolve({ status: \"Pending\" });\n\nconst noRpcSendTx = (): Promise<string> => Promise.reject(new Error(POLKADOT_SEND_TX_HINT));\n\nconst noRpcSendTxToChain = (): Promise<string> =>\n Promise.reject(new Error(POLKADOT_SEND_TX_TO_CHAIN_HINT));\n\nexport { noRpcBalance, noRpcSendTx, noRpcSendTxToChain, noRpcTransactionReceipt };\n","const GENERIC_POLKADOT_ICON =\n \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTYiIGZpbGw9IiNFNjAwN0EiLz48L3N2Zz4=\";\n\nexport { GENERIC_POLKADOT_ICON };\n","/**\n * Minimal local types for the `@polkadot/extension-dapp` injectedWeb3\n * standard. Declared here (rather than depending on\n * `@polkadot/extension-inject`) so the connector stays lean; same\n * posture as `@usebutr/bitcoin`'s `UnisatProvider`. These narrow the\n * spec to only the fields butr reads.\n */\n\n/** A single account the extension exposes. Addresses are SS58; accounts\n * are chain-agnostic across Substrate. */\ntype InjectedAccount = {\n address: string;\n genesisHash?: string | null;\n name?: string;\n type?: string;\n};\n\n/** The polkadot-js `Signer`: butr only uses `signRaw` for message\n * signing. `signPayload` is consumer territory (via polkadot-api). */\ntype InjectedSigner = {\n signRaw?: (raw: {\n address: string;\n data: string;\n type: \"bytes\" | \"payload\";\n }) => Promise<{ id: number; signature: string }>;\n};\n\n/** The object returned by `enable()`. */\ntype Injected = {\n accounts: {\n get: () => Promise<ReadonlyArray<InjectedAccount>>;\n subscribe?: (cb: (accounts: ReadonlyArray<InjectedAccount>) => void) => () => void;\n };\n signer: InjectedSigner;\n};\n\n/** What lives at `window.injectedWeb3[key]`. */\ntype InjectedWindowProvider = {\n enable: (origin: string) => Promise<Injected>;\n version?: string;\n};\n\ntype InjectedWindow = {\n injectedWeb3?: Record<string, InjectedWindowProvider>;\n};\n\nconst BYTES_PREFIX = new TextEncoder().encode(\"<Bytes>\");\nconst BYTES_SUFFIX = new TextEncoder().encode(\"</Bytes>\");\n\nconst wrapBytes = (message: Uint8Array): Uint8Array => {\n const out = new Uint8Array(BYTES_PREFIX.length + message.length + BYTES_SUFFIX.length);\n out.set(BYTES_PREFIX, 0);\n out.set(message, BYTES_PREFIX.length);\n out.set(BYTES_SUFFIX, BYTES_PREFIX.length + message.length);\n return out;\n};\n\nconst readInjectedWindow = (target?: InjectedWindow | null): InjectedWindow | null => {\n if (target !== undefined) {\n return target;\n }\n if (typeof window === \"undefined\") {\n return null;\n }\n // `window.injectedWeb3` is the untyped Polkadot extension registry; the\n // DOM lib doesn't declare it, so this boundary assertion is unavoidable.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- untyped window.injectedWeb3 extension registry\n return window as unknown as InjectedWindow;\n};\n\nexport type { Injected, InjectedAccount, InjectedSigner, InjectedWindow, InjectedWindowProvider };\nexport { bytesToHexPrefixed as bytesToHex, hexToBytes } from \"@usebutr/core\";\nexport { readInjectedWindow, wrapBytes };\n","import type {\n Account,\n ChainBase,\n ConnectorEvent,\n PolkadotAdapter,\n WalletCapabilities,\n} from \"@usebutr/core\";\nimport { sanitizeIcon } from \"@usebutr/core\";\n\nimport { resolveInjectedPolkadotCapabilities } from \"../capabilities\";\nimport { POLKADOT_CHAINS } from \"../chains\";\nimport { noRpcBalance, noRpcSendTx, noRpcSendTxToChain, noRpcTransactionReceipt } from \"../no-rpc\";\n\nimport { GENERIC_POLKADOT_ICON } from \"./icon\";\nimport type { Injected, InjectedWindowProvider } from \"./injected-web3\";\nimport { bytesToHex, hexToBytes, wrapBytes } from \"./injected-web3\";\n\nconst DAPP_NAME = \"butr\";\n\n/** Handle returned by `getSigner()`. Carries the `window.injectedWeb3`\n * key (`extensionName`) so consumers can bridge to polkadot-api's\n * `connectInjectedExtension`, the active SS58 address, and the raw\n * `Injected` object for direct `signer` access. */\ntype PolkadotSignerHandle = {\n address: string;\n extension: Injected;\n extensionName: string;\n};\n\n/**\n * Convert a wallet display name into a stable kebab-case slug for the\n * injected adapter id. Strips anything that isn't a lowercase letter or\n * digit (turning \"Polkadot{.js}\" → \"polkadot-js\"), then prepends the\n * injected Polkadot channel prefix.\n *\n * This is intentionally NOT the wallet-standard-shared `slugify` helper;\n * that helper embeds the `wallet-standard:` scheme which is wrong for\n * the injected channel. The ID convention for injected adapters is\n * `injected:polkadot:<slug>`.\n */\nconst toKebab = (name: string): string =>\n name\n .trim()\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/gv, \"-\")\n .replaceAll(/^-|-$/gv, \"\");\n\nconst buildPolkadotAccount = (address: string, chain: ChainBase): Account => ({\n chain,\n id: `${chain.id}:${address}`,\n walletAddress: address,\n});\n\n/**\n * Wrap a `window.injectedWeb3[name]` provider into a butr\n * `PolkadotAdapter`. The provider is NOT enabled at construction;\n * `enable()` triggers the authorization prompt, so it runs lazily in\n * `connect()`. Before connect, `getAccount` returns null.\n *\n * `id` is `injected:polkadot:<slug>` so consumers can distinguish the\n * injected channel from the Wallet Standard one in their picker.\n */\nconst buildInjectedPolkadotAdapter = (\n extensionName: string,\n displayName: string,\n provider: InjectedWindowProvider,\n): PolkadotAdapter => {\n const capabilities: WalletCapabilities = resolveInjectedPolkadotCapabilities();\n let injected: Injected | null = null;\n let chain: ChainBase = POLKADOT_CHAINS.polkadot;\n const listenersSet = new Set<(event: ConnectorEvent) => void>();\n\n const requireInjected = (): Injected => {\n if (injected === null) {\n throw new Error(`Wallet ${displayName} is not connected`);\n }\n return injected;\n };\n\n const firstAddress = async (): Promise<string | null> => {\n if (injected === null) {\n return null;\n }\n const accounts = await injected.accounts.get();\n return accounts[0]?.address ?? null;\n };\n\n return {\n capabilities,\n chainPlatform: \"polkadot\",\n\n async connect() {\n injected = await provider.enable(DAPP_NAME);\n const accounts = await injected.accounts.get();\n if (accounts.length === 0) {\n throw new Error(`Wallet ${displayName} exposed no accounts`);\n }\n },\n\n disconnect: () => {\n injected = null;\n return Promise.resolve();\n },\n\n async getAccount() {\n const address = await firstAddress();\n return address === null ? null : buildPolkadotAccount(address, chain);\n },\n\n async getAccounts() {\n if (injected === null) {\n return [];\n }\n const accounts = await injected.accounts.get();\n return accounts.map((a) => buildPolkadotAccount(a.address, chain));\n },\n\n getBalance: noRpcBalance,\n\n async getSigner() {\n const ext = requireInjected();\n const address = await firstAddress();\n if (address === null) {\n throw new Error(\"No connected account\");\n }\n const handle: PolkadotSignerHandle = { address, extension: ext, extensionName };\n return handle;\n },\n\n getTransactionReceipt: noRpcTransactionReceipt,\n\n icon: sanitizeIcon(GENERIC_POLKADOT_ICON),\n id: `injected:polkadot:${toKebab(extensionName)}`,\n name: displayName,\n\n sendTx: noRpcSendTx,\n\n sendTxToChain: noRpcSendTxToChain,\n\n async signMessage(msg, account) {\n const ext = requireInjected();\n if (ext.signer.signRaw === undefined) {\n throw new Error(`Wallet ${displayName} does not expose signRaw`);\n }\n const address = account?.walletAddress ?? (await firstAddress());\n if (address === null || address === \"\") {\n throw new Error(\"No connected account\");\n }\n const wrapped = wrapBytes(msg);\n const result = await ext.signer.signRaw({\n address,\n data: bytesToHex(wrapped),\n type: \"bytes\",\n });\n return { signature: hexToBytes(result.signature), signedMessage: wrapped };\n },\n\n subscribe(listener) {\n listenersSet.add(listener);\n let unsubWallet: (() => void) | null = null;\n if (injected?.accounts.subscribe) {\n unsubWallet = injected.accounts.subscribe((accounts) => {\n if (accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const built = accounts.map((a) => buildPolkadotAccount(a.address, chain));\n const first = built[0];\n if (first !== undefined) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n });\n }\n return () => {\n listenersSet.delete(listener);\n unsubWallet?.();\n };\n },\n\n switchChain: (target) => {\n if (target.namespace !== \"polkadot\") {\n return Promise.reject(\n new Error(\n `Polkadot adapter received non-Polkadot chain \"${target.id}\". Pass a chain with namespace \"polkadot\".`,\n ),\n );\n }\n chain = target;\n return Promise.resolve();\n },\n };\n};\n\nexport type { PolkadotSignerHandle };\nexport { buildInjectedPolkadotAdapter };\n","import type { WalletAdapter } from \"@usebutr/core\";\n\nimport { buildInjectedPolkadotAdapter } from \"./adapter\";\nimport type { InjectedWindow } from \"./injected-web3\";\nimport { readInjectedWindow } from \"./injected-web3\";\n\nconst KNOWN_NAMES: Readonly<Record<string, string>> = {\n enkrypt: \"Enkrypt\",\n \"nova-wallet\": \"Nova Wallet\",\n \"polkadot-js\": \"Polkadot{.js}\",\n \"subwallet-js\": \"SubWallet\",\n talisman: \"Talisman\",\n};\n\nconst displayNameFor = (key: string): string =>\n KNOWN_NAMES[key] ??\n key\n .split(/[\\-_]/v)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n\ntype InjectedPolkadotDiscoveryOptions = {\n /** Poll schedule (ms offsets) for late-injecting extensions. Defaults\n * to a few short polls; pass `[]` in tests for a single sync read. */\n pollMs?: ReadonlyArray<number>;\n /** Override the global host (tests, iframes). */\n target?: InjectedWindow | null;\n};\n\nconst DEFAULT_POLLS: ReadonlyArray<number> = [250, 750];\n\n/**\n * Primary Polkadot discovery: enumerate `window.injectedWeb3` keys and\n * emit one `PolkadotAdapter` per extension. Adapters are built WITHOUT\n * calling `enable()` (no prompt at discovery time); `connect()` enables\n * lazily.\n *\n * Extensions inject at different times during page load, so we read\n * immediately and re-check on a short poll schedule, deduping by key.\n */\nconst discoverInjectedPolkadotAdapters = (\n onAdapter: (adapter: WalletAdapter) => void,\n options: InjectedPolkadotDiscoveryOptions = {},\n): (() => void) => {\n const polls = options.pollMs ?? DEFAULT_POLLS;\n const seen = new Set<string>();\n const timers: Array<ReturnType<typeof setTimeout>> = [];\n let cancelled = false;\n\n const scan = () => {\n if (cancelled) {\n return;\n }\n const host = readInjectedWindow(options.target);\n const registry = host?.injectedWeb3;\n if (!registry) {\n return;\n }\n for (const [key, provider] of Object.entries(registry)) {\n if (seen.has(key)) {\n continue;\n }\n seen.add(key);\n onAdapter(buildInjectedPolkadotAdapter(key, displayNameFor(key), provider));\n }\n };\n\n // Always do one synchronous read so tests (and fast extensions) don't\n // wait for a timer.\n scan();\n for (const offset of polls) {\n if (offset === 0) {\n continue;\n }\n timers.push(setTimeout(scan, offset));\n }\n\n return () => {\n cancelled = true;\n for (const timer of timers) {\n clearTimeout(timer);\n }\n };\n};\n\nexport type { InjectedPolkadotDiscoveryOptions };\nexport { discoverInjectedPolkadotAdapters };\n","import type { ChainBase, ConnectorEvent, WalletAdapter } from \"@usebutr/core\";\nimport { logWarn, sanitizeIcon } from \"@usebutr/core\";\nimport {\n buildAccount,\n getFeature,\n pickAccountByAddress,\n pickFirstAddress,\n slugify as kitSlugify,\n} from \"@usebutr/wallet-standard-shared\";\nimport type {\n StandardConnectFeature,\n StandardDisconnectFeature,\n StandardEventsFeature,\n WalletStandardWallet,\n} from \"@usebutr/wallet-standard-shared\";\n\nimport { resolveWalletStandardPolkadotCapabilities } from \"./capabilities\";\nimport { noRpcBalance, noRpcSendTx, noRpcSendTxToChain, noRpcTransactionReceipt } from \"./no-rpc\";\nimport type { PolkadotSignMessageFeature } from \"./wallet-standard-types\";\n\nconst POLKADOT_PREFIX = \"polkadot:\";\n\nconst slugify = (name: string): string => kitSlugify(\"polkadot\", name);\n\nconst pickPolkadotChain = (wallet: WalletStandardWallet): string | null =>\n wallet.chains.find((c) => c.startsWith(POLKADOT_PREFIX)) ?? null;\n\nconst buildChain = (chainId: string, walletName: string): ChainBase => ({\n id: chainId,\n name: walletName,\n namespace: \"polkadot\",\n reference: chainId.slice(POLKADOT_PREFIX.length),\n});\n\n/**\n * Adapt a Wallet Standard wallet advertising `polkadot:*` features into a\n * butr `WalletAdapter`. Returns `null` for wallets that don't advertise a\n * polkadot chain or `standard:connect`. butr ships no RPC, so\n * sendTx/getBalance/getTransactionReceipt are placeholders; transaction\n * signing goes through `getSigner()` (returns the Wallet Standard wallet).\n */\nconst buildPolkadotWalletStandardAdapter = (\n wallet: WalletStandardWallet,\n registerDisconnector?: (emit: () => void) => void,\n): WalletAdapter | null => {\n const chainId = pickPolkadotChain(wallet);\n if (chainId === null) {\n return null;\n }\n const connect = getFeature<StandardConnectFeature>(wallet, \"standard:connect\");\n if (connect === undefined) {\n return null;\n }\n\n const disconnect = getFeature<StandardDisconnectFeature>(wallet, \"standard:disconnect\");\n const events = getFeature<StandardEventsFeature>(wallet, \"standard:events\");\n const signMessage = getFeature<PolkadotSignMessageFeature>(wallet, \"polkadot:signMessage\");\n\n let currentChainId = chainId;\n const currentChain = (): ChainBase => buildChain(currentChainId, wallet.name);\n\n const listeners = new Set<(event: ConnectorEvent) => void>();\n const notifyAccountChanged = () => {\n if (wallet.accounts.length === 0) {\n return;\n }\n const chain = currentChain();\n const built = wallet.accounts.map((a) => buildAccount(a.address, chain));\n const first = built[0];\n if (first === undefined) {\n return;\n }\n for (const listener of listeners) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n };\n\n registerDisconnector?.(() => {\n for (const listener of listeners) {\n listener({ type: \"disconnected\" });\n }\n });\n\n return {\n capabilities: resolveWalletStandardPolkadotCapabilities({\n chainCount: wallet.chains.filter((c) => c.startsWith(POLKADOT_PREFIX)).length,\n features: { events: Boolean(events), signMessage: Boolean(signMessage) },\n }),\n chainPlatform: \"polkadot\",\n\n async connect(opts) {\n await connect.connect(opts?.silent === true ? { silent: true } : undefined);\n },\n\n async disconnect() {\n if (disconnect !== undefined) {\n try {\n await disconnect.disconnect();\n } catch (error) {\n logWarn(\"[butr] Polkadot Wallet Standard disconnect threw:\", error);\n }\n }\n },\n\n getAccount: () => {\n const address = pickFirstAddress(wallet.accounts);\n return Promise.resolve(address === null ? null : buildAccount(address, currentChain()));\n },\n\n getAccounts: () => {\n const chain = currentChain();\n return Promise.resolve(wallet.accounts.map((a) => buildAccount(a.address, chain)));\n },\n\n getBalance: noRpcBalance,\n\n getSigner: () => Promise.resolve(wallet),\n\n getTransactionReceipt: noRpcTransactionReceipt,\n\n icon: sanitizeIcon(wallet.icon),\n id: slugify(wallet.name),\n name: wallet.name,\n\n sendTx: noRpcSendTx,\n\n sendTxToChain: noRpcSendTxToChain,\n\n async signMessage(msg, account) {\n if (signMessage === undefined) {\n throw new Error(`Wallet ${wallet.name} does not advertise polkadot:signMessage`);\n }\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : wallet.accounts[0];\n if (wsAccount === undefined) {\n throw new Error(\"No connected account\");\n }\n const output = await signMessage.signMessage({ account: wsAccount, message: msg });\n return { signature: output.signature, signedMessage: output.signedMessage ?? msg };\n },\n\n subscribe(listener) {\n listeners.add(listener);\n let unsubWallet: (() => void) | null = null;\n if (events !== undefined) {\n const unsub = events.on(\"change\", (changes) => {\n if (changes.accounts !== undefined) {\n if (changes.accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const chain = currentChain();\n const built = changes.accounts.map((a) => buildAccount(a.address, chain));\n const first = built[0];\n if (first !== undefined) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n }\n });\n unsubWallet = () => {\n unsub();\n };\n }\n return () => {\n listeners.delete(listener);\n unsubWallet?.();\n };\n },\n\n switchChain: (target) => {\n if (target.namespace !== \"polkadot\") {\n throw new Error(\n `Polkadot adapter received non-Polkadot chain \"${target.id}\". Pass a chain with namespace \"polkadot\".`,\n );\n }\n if (!wallet.chains.includes(target.id)) {\n throw new Error(\n `Wallet ${wallet.name} does not advertise chain \"${target.id}\". Available: ${wallet.chains.join(\", \")}`,\n );\n }\n currentChainId = target.id;\n notifyAccountChanged();\n return Promise.resolve();\n },\n };\n};\n\nexport { buildPolkadotWalletStandardAdapter };\n","import type { WalletAdapter } from \"@usebutr/core\";\nimport { discoverWalletStandard } from \"@usebutr/wallet-standard-shared\";\n\nimport { buildPolkadotWalletStandardAdapter } from \"./wallet-standard-adapter\";\n\n/**\n * Subscribe to Wallet Standard announcements and emit adapters for\n * wallets advertising `polkadot:*` features (Talisman, SubWallet). Used\n * as the FALLBACK channel; see `polkadotDiscoverer`. Requires the\n * optional `@wallet-standard/app` peer dep; absent → no-op.\n */\nconst discoverPolkadotWalletStandardAdapters = (\n onAdapter: (adapter: WalletAdapter) => void,\n): (() => void) =>\n discoverWalletStandard(onAdapter, (wallet, registerDisconnector) =>\n buildPolkadotWalletStandardAdapter(wallet, registerDisconnector),\n );\n\nexport { discoverPolkadotWalletStandardAdapters };\n","import type { PlatformDiscoverer } from \"@usebutr/core\";\n\nimport { discoverInjectedPolkadotAdapters } from \"./injected\";\nimport { discoverPolkadotWalletStandardAdapters } from \"./wallet-standard\";\n\n/**\n * Polkadot's `PlatformDiscoverer`. Inverts the Bitcoin layout:\n * - PRIMARY (`subscribe`) is injectedWeb3; the dominant, broadest\n * Polkadot standard (polkadot-js, Talisman, SubWallet, Nova, Enkrypt).\n * - FALLBACK is Wallet Standard `polkadot:*`. It defers when the primary\n * channel already produced an adapter for the session\n * (`hasAnyPrimaryAdapter`). Since Wallet Standard support is always\n * additive on Polkadot today (Talisman/SubWallet expose both), the\n * discovery-bus also dedups overlaps and the defer prevents\n * double-listing.\n */\nconst polkadotDiscoverer: PlatformDiscoverer = {\n fallback: {\n subscribe: (onAdapter, opts) => {\n // Defer entirely when injected discovery has already surfaced a\n // wallet; no Polkadot wallet is Wallet-Standard-only today.\n if (opts.hasAnyPrimaryAdapter()) {\n return () => undefined;\n }\n return discoverPolkadotWalletStandardAdapters(onAdapter);\n },\n },\n platform: \"polkadot\",\n subscribe: discoverInjectedPolkadotAdapters,\n};\n\nexport { polkadotDiscoverer };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["slugify","kitSlugify"],"sources":["../src/chains.ts","../src/capabilities.ts","../src/no-rpc.ts","../src/injected/icon.ts","../src/injected/injected-web3.ts","../src/injected/adapter.ts","../src/injected/index.ts","../src/wallet-standard-adapter.ts","../src/discoverer.ts"],"sourcesContent":["import type { ChainBase } from \"@usebutr/core\";\n\n// CAIP-2 for Polkadot is `polkadot:{first-32-hex-of-genesis-hash}`.\n// injectedWeb3 doesn't advertise chains (accounts are chain-agnostic\n// across Substrate), so this registry is butr-authored. Wallet Standard\n// polkadot wallets advertise these same CAIP-2 ids.\nconst POLKADOT_CHAINS = {\n kusama: {\n id: \"polkadot:b0a8d493285c2df73290dfb7e61f870f\",\n name: \"Kusama\",\n namespace: \"polkadot\",\n reference: \"b0a8d493285c2df73290dfb7e61f870f\",\n },\n paseo: {\n id: \"polkadot:77afd6190f1554ad45fd0d31aee62aac\",\n name: \"Paseo\",\n namespace: \"polkadot\",\n reference: \"77afd6190f1554ad45fd0d31aee62aac\",\n },\n polkadot: {\n id: \"polkadot:91b171bb158e2d3848fa23a9f1c25182\",\n name: \"Polkadot\",\n namespace: \"polkadot\",\n reference: \"91b171bb158e2d3848fa23a9f1c25182\",\n },\n westend: {\n id: \"polkadot:e143f23803ac50e8f6f8e62695d1ce9e\",\n name: \"Westend\",\n namespace: \"polkadot\",\n reference: \"e143f23803ac50e8f6f8e62695d1ce9e\",\n },\n} as const satisfies Record<string, ChainBase>;\n\nconst POLKADOT_CHAINS_LIST: ReadonlyArray<ChainBase> = Object.values(POLKADOT_CHAINS);\n\nexport { POLKADOT_CHAINS, POLKADOT_CHAINS_LIST };\n","import type { WalletCapabilities } from \"@usebutr/core\";\nimport { buildWalletCapabilities } from \"@usebutr/wallet-standard-shared\";\n\nimport { POLKADOT_CHAINS_LIST } from \"./chains\";\n\ntype WalletStandardPolkadotCapabilityInput = {\n chainCount: number;\n features: {\n events: boolean;\n signMessage: boolean;\n };\n};\n\n/**\n * injectedWeb3 capability profile. The injected `signer.signRaw` always\n * supports message signing and `accounts.subscribe` always supports events,\n * so both are unconditional. The chain count comes from butr's own registry\n * because injectedWeb3 wallets advertise no chains of their own.\n */\nconst resolveInjectedPolkadotCapabilities = (): WalletCapabilities =>\n buildWalletCapabilities({\n chainCount: POLKADOT_CHAINS_LIST.length,\n events: true,\n sendTransaction: false,\n signIn: false,\n signMessage: true,\n signTransaction: false,\n });\n\n/**\n * Wallet Standard `polkadot:*` feature → butr capability mapping. No\n * standalone `signTransaction`: building an extrinsic needs chain metadata\n * butr doesn't fetch, so transaction signing goes through `getSigner()`.\n */\nconst resolveWalletStandardPolkadotCapabilities = (\n input: WalletStandardPolkadotCapabilityInput,\n): WalletCapabilities =>\n buildWalletCapabilities({\n chainCount: input.chainCount,\n events: input.features.events,\n sendTransaction: false,\n signIn: false,\n signMessage: input.features.signMessage,\n signTransaction: false,\n });\n\nexport type { WalletStandardPolkadotCapabilityInput };\nexport { resolveInjectedPolkadotCapabilities, resolveWalletStandardPolkadotCapabilities };\n","import type { Balance } from \"@usebutr/core\";\n\n/**\n * butr ships no RPC on Polkadot: building/broadcasting an extrinsic and\n * reading on-chain state both need chain metadata. Balance and receipt\n * reads return neutral placeholders (gated behind\n * `capabilities.getBalance` / `getTransactionReceipt === false`);\n * transaction submission rejects with a hint to drive polkadot-api via\n * `getSigner()`. Both discovery channels (injectedWeb3 + Wallet Standard)\n * share these so the invariant lives in one place.\n */\nconst POLKADOT_SEND_TX_HINT =\n \"Polkadot sendTx is unsupported: use getSigner() with polkadot-api to build and submit extrinsics\";\nconst POLKADOT_SEND_TX_TO_CHAIN_HINT =\n \"Polkadot sendTxToChain is unsupported: use getSigner() with polkadot-api to build and submit extrinsics\";\n\nconst noRpcBalance = (): Promise<Balance> =>\n Promise.resolve({ decimals: 0, formatted: \"0\", symbol: \"\", value: 0n });\n\nconst noRpcTransactionReceipt = (): Promise<{ status: \"Success\" | \"Error\" | \"Pending\" }> =>\n Promise.resolve({ status: \"Pending\" });\n\nconst noRpcSendTx = (): Promise<string> => Promise.reject(new Error(POLKADOT_SEND_TX_HINT));\n\nconst noRpcSendTxToChain = (): Promise<string> =>\n Promise.reject(new Error(POLKADOT_SEND_TX_TO_CHAIN_HINT));\n\nexport { noRpcBalance, noRpcSendTx, noRpcSendTxToChain, noRpcTransactionReceipt };\n","const GENERIC_POLKADOT_ICON =\n \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTYiIGZpbGw9IiNFNjAwN0EiLz48L3N2Zz4=\";\n\nexport { GENERIC_POLKADOT_ICON };\n","/**\n * Minimal local types for the `@polkadot/extension-dapp` injectedWeb3\n * standard. Declared here (rather than depending on\n * `@polkadot/extension-inject`) so the connector stays lean; same\n * posture as `@usebutr/bitcoin`'s `UnisatProvider`. These narrow the\n * spec to only the fields butr reads.\n */\n\n/** A single account the extension exposes. Addresses are SS58; accounts\n * are chain-agnostic across Substrate. */\ntype InjectedAccount = {\n address: string;\n genesisHash?: string | null;\n name?: string;\n type?: string;\n};\n\n/** The polkadot-js `Signer`: butr only uses `signRaw` for message\n * signing. `signPayload` is consumer territory (via polkadot-api). */\ntype InjectedSigner = {\n signRaw?: (raw: {\n address: string;\n data: string;\n type: \"bytes\" | \"payload\";\n }) => Promise<{ id: number; signature: string }>;\n};\n\n/** The object returned by `enable()`. */\ntype Injected = {\n accounts: {\n get: () => Promise<ReadonlyArray<InjectedAccount>>;\n subscribe?: (cb: (accounts: ReadonlyArray<InjectedAccount>) => void) => () => void;\n };\n signer: InjectedSigner;\n};\n\n/** What lives at `window.injectedWeb3[key]`. */\ntype InjectedWindowProvider = {\n enable: (origin: string) => Promise<Injected>;\n version?: string;\n};\n\ntype InjectedWindow = {\n injectedWeb3?: Record<string, InjectedWindowProvider>;\n};\n\nconst BYTES_PREFIX = new TextEncoder().encode(\"<Bytes>\");\nconst BYTES_SUFFIX = new TextEncoder().encode(\"</Bytes>\");\n\nconst wrapBytes = (message: Uint8Array): Uint8Array => {\n const out = new Uint8Array(BYTES_PREFIX.length + message.length + BYTES_SUFFIX.length);\n out.set(BYTES_PREFIX, 0);\n out.set(message, BYTES_PREFIX.length);\n out.set(BYTES_SUFFIX, BYTES_PREFIX.length + message.length);\n return out;\n};\n\nconst readInjectedWindow = (target?: InjectedWindow | null): InjectedWindow | null => {\n if (target !== undefined) {\n return target;\n }\n if (typeof window === \"undefined\") {\n return null;\n }\n // `window.injectedWeb3` is the untyped Polkadot extension registry; the\n // DOM lib doesn't declare it, so this boundary assertion is unavoidable.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- untyped window.injectedWeb3 extension registry\n return window as unknown as InjectedWindow;\n};\n\nexport type { Injected, InjectedAccount, InjectedSigner, InjectedWindow, InjectedWindowProvider };\nexport { bytesToHexPrefixed as bytesToHex, hexToBytes } from \"@usebutr/core\";\nexport { readInjectedWindow, wrapBytes };\n","import type {\n Account,\n ChainBase,\n ConnectorEvent,\n PolkadotAdapter,\n WalletCapabilities,\n} from \"@usebutr/core\";\nimport { sanitizeIcon } from \"@usebutr/core\";\n\nimport { resolveInjectedPolkadotCapabilities } from \"../capabilities\";\nimport { POLKADOT_CHAINS } from \"../chains\";\nimport { noRpcBalance, noRpcSendTx, noRpcSendTxToChain, noRpcTransactionReceipt } from \"../no-rpc\";\n\nimport { GENERIC_POLKADOT_ICON } from \"./icon\";\nimport type { Injected, InjectedWindowProvider } from \"./injected-web3\";\nimport { bytesToHex, hexToBytes, wrapBytes } from \"./injected-web3\";\n\nconst DAPP_NAME = \"butr\";\n\n/** Handle returned by `getSigner()`. Carries the `window.injectedWeb3`\n * key (`extensionName`) so consumers can bridge to polkadot-api's\n * `connectInjectedExtension`, the active SS58 address, and the raw\n * `Injected` object for direct `signer` access. */\ntype PolkadotSignerHandle = {\n address: string;\n extension: Injected;\n extensionName: string;\n};\n\n/**\n * Convert a wallet display name into a stable kebab-case slug for the\n * injected adapter id. Strips anything that isn't a lowercase letter or\n * digit (turning \"Polkadot{.js}\" → \"polkadot-js\"), then prepends the\n * injected Polkadot channel prefix.\n *\n * This is intentionally NOT the wallet-standard-shared `slugify` helper;\n * that helper embeds the `wallet-standard:` scheme which is wrong for\n * the injected channel. The ID convention for injected adapters is\n * `injected:polkadot:<slug>`.\n */\nconst toKebab = (name: string): string =>\n name\n .trim()\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/gv, \"-\")\n .replaceAll(/^-|-$/gv, \"\");\n\nconst buildPolkadotAccount = (address: string, chain: ChainBase): Account => ({\n chain,\n id: `${chain.id}:${address}`,\n walletAddress: address,\n});\n\n/**\n * Wrap a `window.injectedWeb3[name]` provider into a butr\n * `PolkadotAdapter`. The provider is NOT enabled at construction;\n * `enable()` triggers the authorization prompt, so it runs lazily in\n * `connect()`. Before connect, `getAccount` returns null.\n *\n * `id` is `injected:polkadot:<slug>` so consumers can distinguish the\n * injected channel from the Wallet Standard one in their picker.\n */\nconst buildInjectedPolkadotAdapter = (\n extensionName: string,\n displayName: string,\n provider: InjectedWindowProvider,\n): PolkadotAdapter => {\n const capabilities: WalletCapabilities = resolveInjectedPolkadotCapabilities();\n let injected: Injected | null = null;\n let chain: ChainBase = POLKADOT_CHAINS.polkadot;\n const listenersSet = new Set<(event: ConnectorEvent) => void>();\n\n const requireInjected = (): Injected => {\n if (injected === null) {\n throw new Error(`Wallet ${displayName} is not connected`);\n }\n return injected;\n };\n\n const firstAddress = async (): Promise<string | null> => {\n if (injected === null) {\n return null;\n }\n const accounts = await injected.accounts.get();\n return accounts[0]?.address ?? null;\n };\n\n return {\n capabilities,\n chainPlatform: \"polkadot\",\n\n async connect() {\n injected = await provider.enable(DAPP_NAME);\n const accounts = await injected.accounts.get();\n if (accounts.length === 0) {\n throw new Error(`Wallet ${displayName} exposed no accounts`);\n }\n },\n\n disconnect: () => {\n injected = null;\n return Promise.resolve();\n },\n\n async getAccount() {\n const address = await firstAddress();\n return address === null ? null : buildPolkadotAccount(address, chain);\n },\n\n async getAccounts() {\n if (injected === null) {\n return [];\n }\n const accounts = await injected.accounts.get();\n return accounts.map((a) => buildPolkadotAccount(a.address, chain));\n },\n\n getBalance: noRpcBalance,\n\n async getSigner() {\n const ext = requireInjected();\n const address = await firstAddress();\n if (address === null) {\n throw new Error(\"No connected account\");\n }\n const handle: PolkadotSignerHandle = { address, extension: ext, extensionName };\n return handle;\n },\n\n getTransactionReceipt: noRpcTransactionReceipt,\n\n icon: sanitizeIcon(GENERIC_POLKADOT_ICON),\n id: `injected:polkadot:${toKebab(extensionName)}`,\n name: displayName,\n\n sendTx: noRpcSendTx,\n\n sendTxToChain: noRpcSendTxToChain,\n\n async signMessage(msg, account) {\n const ext = requireInjected();\n if (ext.signer.signRaw === undefined) {\n throw new Error(`Wallet ${displayName} does not expose signRaw`);\n }\n const address = account?.walletAddress ?? (await firstAddress());\n if (address === null || address === \"\") {\n throw new Error(\"No connected account\");\n }\n const wrapped = wrapBytes(msg);\n const result = await ext.signer.signRaw({\n address,\n data: bytesToHex(wrapped),\n type: \"bytes\",\n });\n return { signature: hexToBytes(result.signature), signedMessage: wrapped };\n },\n\n subscribe(listener) {\n listenersSet.add(listener);\n let unsubWallet: (() => void) | null = null;\n if (injected?.accounts.subscribe) {\n unsubWallet = injected.accounts.subscribe((accounts) => {\n if (accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const built = accounts.map((a) => buildPolkadotAccount(a.address, chain));\n const first = built[0];\n if (first !== undefined) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n });\n }\n return () => {\n listenersSet.delete(listener);\n unsubWallet?.();\n };\n },\n\n switchChain: (target) => {\n if (target.namespace !== \"polkadot\") {\n return Promise.reject(\n new Error(\n `Polkadot adapter received non-Polkadot chain \"${target.id}\". Pass a chain with namespace \"polkadot\".`,\n ),\n );\n }\n chain = target;\n return Promise.resolve();\n },\n };\n};\n\nexport type { PolkadotSignerHandle };\nexport { buildInjectedPolkadotAdapter };\n","import type { WalletAdapter } from \"@usebutr/core\";\n\nimport { buildInjectedPolkadotAdapter } from \"./adapter\";\nimport type { InjectedWindow } from \"./injected-web3\";\nimport { readInjectedWindow } from \"./injected-web3\";\n\nconst KNOWN_NAMES: Readonly<Record<string, string>> = {\n enkrypt: \"Enkrypt\",\n \"nova-wallet\": \"Nova Wallet\",\n \"polkadot-js\": \"Polkadot{.js}\",\n \"subwallet-js\": \"SubWallet\",\n talisman: \"Talisman\",\n};\n\nconst displayNameFor = (key: string): string =>\n KNOWN_NAMES[key] ??\n key\n .split(/[\\-_]/v)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n\ntype InjectedPolkadotDiscoveryOptions = {\n /** Poll schedule (ms offsets) for late-injecting extensions. Defaults\n * to a few short polls; pass `[]` in tests for a single sync read. */\n pollMs?: ReadonlyArray<number>;\n /** Override the global host (tests, iframes). */\n target?: InjectedWindow | null;\n};\n\nconst DEFAULT_POLLS: ReadonlyArray<number> = [250, 750];\n\n/**\n * Primary Polkadot discovery: enumerate `window.injectedWeb3` keys and\n * emit one `PolkadotAdapter` per extension. Adapters are built WITHOUT\n * calling `enable()` (no prompt at discovery time); `connect()` enables\n * lazily.\n *\n * Extensions inject at different times during page load, so we read\n * immediately and re-check on a short poll schedule, deduping by key.\n */\nconst discoverInjectedPolkadotAdapters = (\n onAdapter: (adapter: WalletAdapter) => void,\n options: InjectedPolkadotDiscoveryOptions = {},\n): (() => void) => {\n const polls = options.pollMs ?? DEFAULT_POLLS;\n const seen = new Set<string>();\n const timers: Array<ReturnType<typeof setTimeout>> = [];\n let cancelled = false;\n\n const scan = () => {\n if (cancelled) {\n return;\n }\n const host = readInjectedWindow(options.target);\n const registry = host?.injectedWeb3;\n if (!registry) {\n return;\n }\n for (const [key, provider] of Object.entries(registry)) {\n if (seen.has(key)) {\n continue;\n }\n seen.add(key);\n onAdapter(buildInjectedPolkadotAdapter(key, displayNameFor(key), provider));\n }\n };\n\n // Always do one synchronous read so tests (and fast extensions) don't\n // wait for a timer.\n scan();\n for (const offset of polls) {\n if (offset === 0) {\n continue;\n }\n timers.push(setTimeout(scan, offset));\n }\n\n return () => {\n cancelled = true;\n for (const timer of timers) {\n clearTimeout(timer);\n }\n };\n};\n\nexport type { InjectedPolkadotDiscoveryOptions };\nexport { discoverInjectedPolkadotAdapters };\n","import type { WalletAdapter } from \"@usebutr/core\";\nimport {\n createWalletStandardCore,\n discoverWalletStandard,\n getFeature,\n slugify as kitSlugify,\n} from \"@usebutr/wallet-standard-shared\";\nimport type { WalletStandardWallet } from \"@usebutr/wallet-standard-shared\";\n\nimport { resolveWalletStandardPolkadotCapabilities } from \"./capabilities\";\nimport { noRpcBalance, noRpcSendTx, noRpcSendTxToChain, noRpcTransactionReceipt } from \"./no-rpc\";\nimport type { PolkadotSignMessageFeature } from \"./wallet-standard-types\";\n\nconst POLKADOT_PREFIX = \"polkadot:\";\n\nconst slugify = (name: string): string => kitSlugify(\"polkadot\", name);\n\n/**\n * Adapt a Wallet Standard wallet advertising `polkadot:*` features into a\n * butr `WalletAdapter`. Returns `null` for wallets that don't advertise a\n * polkadot chain or `standard:connect`. butr ships no RPC, so\n * sendTx/getBalance/getTransactionReceipt are placeholders; transaction\n * signing goes through `getSigner()` (returns the Wallet Standard wallet).\n */\nconst buildPolkadotWalletStandardAdapter = (\n wallet: WalletStandardWallet,\n /** Optional. Called with a function that pushes a synthetic\n * `disconnected` event to all current subscribers. The discovery\n * layer invokes it on Wallet Standard `unregister`. */\n registerDisconnector?: (emit: () => void) => void,\n): WalletAdapter | null => {\n const core = createWalletStandardCore({\n chainPrefix: POLKADOT_PREFIX,\n id: slugify(wallet.name),\n label: \"Polkadot\",\n namespace: \"polkadot\",\n platform: \"Polkadot\",\n preferredChainIds: [],\n registerDisconnector,\n // Polkadot wallets advertise a single relay chain, so a wallet-side\n // `chains` change has no better chain to move to.\n trackChainChanges: false,\n wallet,\n });\n if (core === null) {\n return null;\n }\n\n const signMessage = getFeature<PolkadotSignMessageFeature>(wallet, \"polkadot:signMessage\");\n\n return {\n ...core,\n capabilities: resolveWalletStandardPolkadotCapabilities({\n chainCount: core.chainCount,\n features: { events: core.hasEvents, signMessage: Boolean(signMessage) },\n }),\n chainPlatform: \"polkadot\",\n\n getBalance: noRpcBalance,\n\n getTransactionReceipt: noRpcTransactionReceipt,\n\n sendTx: noRpcSendTx,\n\n sendTxToChain: noRpcSendTxToChain,\n\n async signMessage(msg, account) {\n if (signMessage === undefined) {\n throw new Error(`Wallet ${wallet.name} does not advertise polkadot:signMessage`);\n }\n const output = await signMessage.signMessage({\n account: core.resolveAccount(account),\n message: msg,\n });\n return { signature: output.signature, signedMessage: output.signedMessage ?? msg };\n },\n };\n};\n\n/**\n * Subscribe to Wallet Standard announcements and emit adapters for\n * wallets advertising `polkadot:*` features (Talisman, SubWallet). Used\n * as the FALLBACK channel; see `polkadotDiscoverer`. Requires the\n * optional `@wallet-standard/app` peer dep; absent → no-op.\n */\nconst discoverPolkadotWalletStandardAdapters = (\n onAdapter: (adapter: WalletAdapter) => void,\n): (() => void) =>\n discoverWalletStandard(onAdapter, (wallet, registerDisconnector) =>\n buildPolkadotWalletStandardAdapter(wallet, registerDisconnector),\n );\n\nexport { buildPolkadotWalletStandardAdapter, discoverPolkadotWalletStandardAdapters };\n","import type { PlatformDiscoverer } from \"@usebutr/core\";\n\nimport { discoverInjectedPolkadotAdapters } from \"./injected\";\nimport { discoverPolkadotWalletStandardAdapters } from \"./wallet-standard-adapter\";\n\n/**\n * Polkadot's `PlatformDiscoverer`. Inverts the Bitcoin layout:\n * - PRIMARY (`subscribe`) is injectedWeb3; the dominant, broadest\n * Polkadot standard (polkadot-js, Talisman, SubWallet, Nova, Enkrypt).\n * - FALLBACK is Wallet Standard `polkadot:*`. It defers when the primary\n * channel already produced an adapter for the session\n * (`hasAnyPrimaryAdapter`). Since Wallet Standard support is always\n * additive on Polkadot today (Talisman/SubWallet expose both), the\n * discovery-bus also dedups overlaps and the defer prevents\n * double-listing.\n */\nconst polkadotDiscoverer: PlatformDiscoverer = {\n fallback: {\n subscribe: (onAdapter, opts) => {\n // Defer entirely when injected discovery has already surfaced a\n // wallet; no Polkadot wallet is Wallet-Standard-only today.\n if (opts.hasAnyPrimaryAdapter()) {\n return () => undefined;\n }\n return discoverPolkadotWalletStandardAdapters(onAdapter);\n },\n },\n subscribe: discoverInjectedPolkadotAdapters,\n};\n\nexport { polkadotDiscoverer };\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebutr/polkadot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "injectedWeb3 + Wallet Standard adapter for butr (Polkadot/Substrate).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Pedro Filho <pedro@filho.me>",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@usebutr/core": "0.
|
|
29
|
-
"@usebutr/wallet-standard-shared": "0.
|
|
28
|
+
"@usebutr/core": "1.0.0",
|
|
29
|
+
"@usebutr/wallet-standard-shared": "0.4.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@wallet-standard/app": "^1.1.1",
|