@usebutr/polkadot 0.1.0 → 0.1.2
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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +447 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -146,7 +146,7 @@ type PolkadotSignMessageOutput = {
|
|
|
146
146
|
signedMessage?: Uint8Array;
|
|
147
147
|
};
|
|
148
148
|
type PolkadotSignMessageFeature = {
|
|
149
|
-
signMessage(input: PolkadotSignMessageInput)
|
|
149
|
+
signMessage: (input: PolkadotSignMessageInput) => Promise<PolkadotSignMessageOutput>;
|
|
150
150
|
};
|
|
151
151
|
//#endregion
|
|
152
152
|
//#region src/wallet-standard-adapter.d.ts
|
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/wallet-standard.ts","../src/discoverer.ts","../src/signer-augmentation.ts"],"mappings":";;;;cAMM,eAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;cA2BA,oBAAA,EAAsB,aAAa,CAAC,SAAA;;;KC/BrC,qCAAA;EACH,UAAA;EACA,QAAA;IACE,MAAA;IACA,WAAA;EAAA;AAAA;;;;;;;cAgBE,mCAAA,QAA0C,kBAW9C;;;;;;cAOI,yCAAA,GACJ,KAAA,EAAO,qCAAA,KACN,kBAWD;;;;;;;ADrD6C;;;;;KEU1C,eAAA;EACH,OAAA;EACA,WAAA;EACA,IAAA;EACA,IAAA;AAAA;;;KAKG,cAAA;EACH,OAAA,IAAW,GAAA;IACT,OAAA;IACA,IAAA;IACA,IAAA;EAAA,MACI,OAAO;IAAG,EAAA;IAAY,SAAA;EAAA;AAAA;;KAIzB,QAAA;EACH,QAAA;IACE,GAAA,QAAW,OAAA,CAAQ,aAAA,CAAc,eAAA;IACjC,SAAA,IAAa,EAAA,GAAK,QAAA,EAAU,aAAA,CAAc,eAAA;EAAA;EAE5C,MAAA,EAAQ,cAAA;AAAA;;KAIL,sBAAA;EACH,MAAA,GAAS,MAAA,aAAmB,OAAO,CAAC,QAAA;EACpC,OAAA;AAAA;AAAA,KAGG,cAAA;EACH,YAAA,GAAe,MAAM,SAAS,sBAAA;AAAA;;;;;AF3Ce;;KGuB1C,oBAAA;EACH,OAAA;EACA,SAAA,EAAW,QAAQ;EACnB,aAAA;AAAA;;;;;;;;;;cAoCI,4BAAA,GACJ,aAAA,UACA,WAAA,UACA,QAAA,EAAU,sBAAA,KACT,eA+HF;;;KC1KI,gCAAA;;AJvB0C;EI0B7C,MAAA,GAAS,aAAA;EAET,MAAA,GAAS,cAAc;AAAA;;;;;;;;;;cAcnB,gCAAA,GACJ,SAAA,GAAY,OAAA,EAAS,aAAA,WACrB,OAAA,GAAS,gCAAqC;;;KCrC3C,wBAAA;EACH,OAAA,EAAS,2BAAA;EACT,OAAA,EAAS,UAAU;AAAA;AAAA,KAGhB,yBAAA;EACH,SAAA,EAAW,UAAA;EACX,aAAA,GAAgB,UAAU;AAAA;AAAA,KAGvB,0BAAA;EACH,WAAA,
|
|
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/wallet-standard.ts","../src/discoverer.ts","../src/signer-augmentation.ts"],"mappings":";;;;cAMM,eAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;cA2BA,oBAAA,EAAsB,aAAa,CAAC,SAAA;;;KC/BrC,qCAAA;EACH,UAAA;EACA,QAAA;IACE,MAAA;IACA,WAAA;EAAA;AAAA;;;;;;;cAgBE,mCAAA,QAA0C,kBAW9C;;;;;;cAOI,yCAAA,GACJ,KAAA,EAAO,qCAAA,KACN,kBAWD;;;;;;;ADrD6C;;;;;KEU1C,eAAA;EACH,OAAA;EACA,WAAA;EACA,IAAA;EACA,IAAA;AAAA;;;KAKG,cAAA;EACH,OAAA,IAAW,GAAA;IACT,OAAA;IACA,IAAA;IACA,IAAA;EAAA,MACI,OAAO;IAAG,EAAA;IAAY,SAAA;EAAA;AAAA;;KAIzB,QAAA;EACH,QAAA;IACE,GAAA,QAAW,OAAA,CAAQ,aAAA,CAAc,eAAA;IACjC,SAAA,IAAa,EAAA,GAAK,QAAA,EAAU,aAAA,CAAc,eAAA;EAAA;EAE5C,MAAA,EAAQ,cAAA;AAAA;;KAIL,sBAAA;EACH,MAAA,GAAS,MAAA,aAAmB,OAAO,CAAC,QAAA;EACpC,OAAA;AAAA;AAAA,KAGG,cAAA;EACH,YAAA,GAAe,MAAM,SAAS,sBAAA;AAAA;;;;;AF3Ce;;KGuB1C,oBAAA;EACH,OAAA;EACA,SAAA,EAAW,QAAQ;EACnB,aAAA;AAAA;;;;;;;;;;cAoCI,4BAAA,GACJ,aAAA,UACA,WAAA,UACA,QAAA,EAAU,sBAAA,KACT,eA+HF;;;KC1KI,gCAAA;;AJvB0C;EI0B7C,MAAA,GAAS,aAAA;EAET,MAAA,GAAS,cAAc;AAAA;;;;;;;;;;cAcnB,gCAAA,GACJ,SAAA,GAAY,OAAA,EAAS,aAAA,WACrB,OAAA,GAAS,gCAAqC;;;KCrC3C,wBAAA;EACH,OAAA,EAAS,2BAAA;EACT,OAAA,EAAS,UAAU;AAAA;AAAA,KAGhB,yBAAA;EACH,SAAA,EAAW,UAAA;EACX,aAAA,GAAgB,UAAU;AAAA;AAAA,KAGvB,0BAAA;EACH,WAAA,GAAc,KAAA,EAAO,wBAAA,KAA6B,OAAA,CAAQ,yBAAA;AAAA;;;;;ALlBb;;;;;cM2CzC,kCAAA,GACJ,MAAA,EAAQ,oBAAA,EACR,oBAAA,IAAwB,IAAA,0BACvB,aAAa;;;;;;AN9C+B;;;cOWzC,sCAAA,GACJ,SAAA,GAAY,OAAA,EAAS,aAAa;;;;;;APZW;;;;;;;;cQgBzC,kBAAA,EAAoB,kBAazB;;;;;AR7B8C;;;;;;;;;YSgBnC,iBAAA;IACR,QAAA,EAAU,oBAAA,GAAuB,oBAAoB;EAAA;AAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,448 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { bytesToHexPrefixed as bytesToHex, hexToBytes, logWarn, sanitizeIcon } from "@usebutr/core";
|
|
2
|
+
import { buildAccount, discoverWalletStandard, getFeature, pickAccountByAddress, pickFirstAddress, slugify } from "@usebutr/wallet-standard-shared";
|
|
3
|
+
|
|
4
|
+
//#region src/chains.ts
|
|
5
|
+
const POLKADOT_CHAINS = {
|
|
6
|
+
kusama: {
|
|
7
|
+
id: "polkadot:b0a8d493285c2df73290dfb7e61f870f",
|
|
8
|
+
name: "Kusama",
|
|
9
|
+
namespace: "polkadot",
|
|
10
|
+
reference: "b0a8d493285c2df73290dfb7e61f870f"
|
|
11
|
+
},
|
|
12
|
+
paseo: {
|
|
13
|
+
id: "polkadot:77afd6190f1554ad45fd0d31aee62aac",
|
|
14
|
+
name: "Paseo",
|
|
15
|
+
namespace: "polkadot",
|
|
16
|
+
reference: "77afd6190f1554ad45fd0d31aee62aac"
|
|
17
|
+
},
|
|
18
|
+
polkadot: {
|
|
19
|
+
id: "polkadot:91b171bb158e2d3848fa23a9f1c25182",
|
|
20
|
+
name: "Polkadot",
|
|
21
|
+
namespace: "polkadot",
|
|
22
|
+
reference: "91b171bb158e2d3848fa23a9f1c25182"
|
|
23
|
+
},
|
|
24
|
+
westend: {
|
|
25
|
+
id: "polkadot:e143f23803ac50e8f6f8e62695d1ce9e",
|
|
26
|
+
name: "Westend",
|
|
27
|
+
namespace: "polkadot",
|
|
28
|
+
reference: "e143f23803ac50e8f6f8e62695d1ce9e"
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const POLKADOT_CHAINS_LIST = Object.values(POLKADOT_CHAINS);
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/capabilities.ts
|
|
35
|
+
/**
|
|
36
|
+
* injectedWeb3 capability profile. The injected `signer.signRaw` always
|
|
37
|
+
* supports message signing; `accounts.subscribe` always supports events;
|
|
38
|
+
* butr authors the chain list (4 chains) so local switchChain is always
|
|
39
|
+
* available.
|
|
40
|
+
*/
|
|
41
|
+
const resolveInjectedPolkadotCapabilities = () => ({
|
|
42
|
+
getBalance: false,
|
|
43
|
+
getTransactionReceipt: false,
|
|
44
|
+
requestAccounts: false,
|
|
45
|
+
sendTransaction: false,
|
|
46
|
+
signIn: false,
|
|
47
|
+
signMessage: true,
|
|
48
|
+
signTransaction: false,
|
|
49
|
+
subscribe: true,
|
|
50
|
+
switchAccount: false,
|
|
51
|
+
switchChain: true
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Wallet Standard `polkadot:*` capability mapping. Mirrors the Sui/SVM
|
|
55
|
+
* resolvers: features come from what the wallet advertises; switchChain
|
|
56
|
+
* follows chainCount (local re-routing among advertised chains).
|
|
57
|
+
*/
|
|
58
|
+
const resolveWalletStandardPolkadotCapabilities = (input) => ({
|
|
59
|
+
getBalance: false,
|
|
60
|
+
getTransactionReceipt: false,
|
|
61
|
+
requestAccounts: false,
|
|
62
|
+
sendTransaction: false,
|
|
63
|
+
signIn: false,
|
|
64
|
+
signMessage: input.features.signMessage,
|
|
65
|
+
signTransaction: false,
|
|
66
|
+
subscribe: input.features.events,
|
|
67
|
+
switchAccount: false,
|
|
68
|
+
switchChain: input.chainCount > 1
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/no-rpc.ts
|
|
73
|
+
/**
|
|
74
|
+
* butr ships no RPC on Polkadot: building/broadcasting an extrinsic and
|
|
75
|
+
* reading on-chain state both need chain metadata. Balance and receipt
|
|
76
|
+
* reads return neutral placeholders (gated behind
|
|
77
|
+
* `capabilities.getBalance` / `getTransactionReceipt === false`);
|
|
78
|
+
* transaction submission rejects with a hint to drive polkadot-api via
|
|
79
|
+
* `getSigner()`. Both discovery channels (injectedWeb3 + Wallet Standard)
|
|
80
|
+
* share these so the invariant lives in one place.
|
|
81
|
+
*/
|
|
82
|
+
const POLKADOT_SEND_TX_HINT = "Polkadot sendTx is unsupported — use getSigner() with polkadot-api to build and submit extrinsics";
|
|
83
|
+
const POLKADOT_SEND_TX_TO_CHAIN_HINT = "Polkadot sendTxToChain is unsupported — use getSigner() with polkadot-api to build and submit extrinsics";
|
|
84
|
+
const noRpcBalance = () => Promise.resolve({
|
|
85
|
+
decimals: 0,
|
|
86
|
+
formatted: "0",
|
|
87
|
+
symbol: "",
|
|
88
|
+
value: 0n
|
|
89
|
+
});
|
|
90
|
+
const noRpcTransactionReceipt = () => Promise.resolve({ status: "Pending" });
|
|
91
|
+
const noRpcSendTx = () => Promise.reject(/* @__PURE__ */ new Error(POLKADOT_SEND_TX_HINT));
|
|
92
|
+
const noRpcSendTxToChain = () => Promise.reject(/* @__PURE__ */ new Error(POLKADOT_SEND_TX_TO_CHAIN_HINT));
|
|
93
|
+
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/injected/icon.ts
|
|
96
|
+
const GENERIC_POLKADOT_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PGNpcmNsZSBjeD0iMTYiIGN5PSIxNiIgcj0iMTYiIGZpbGw9IiNFNjAwN0EiLz48L3N2Zz4=";
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/injected/injected-web3.ts
|
|
100
|
+
const BYTES_PREFIX = new TextEncoder().encode("<Bytes>");
|
|
101
|
+
const BYTES_SUFFIX = new TextEncoder().encode("</Bytes>");
|
|
102
|
+
const wrapBytes = (message) => {
|
|
103
|
+
const out = new Uint8Array(BYTES_PREFIX.length + message.length + BYTES_SUFFIX.length);
|
|
104
|
+
out.set(BYTES_PREFIX, 0);
|
|
105
|
+
out.set(message, BYTES_PREFIX.length);
|
|
106
|
+
out.set(BYTES_SUFFIX, BYTES_PREFIX.length + message.length);
|
|
107
|
+
return out;
|
|
108
|
+
};
|
|
109
|
+
const readInjectedWindow = (target) => {
|
|
110
|
+
if (target !== void 0) return target;
|
|
111
|
+
return typeof window === "undefined" ? null : window;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/injected/adapter.ts
|
|
116
|
+
const DAPP_NAME = "butr";
|
|
117
|
+
/**
|
|
118
|
+
* Convert a wallet display name into a stable kebab-case slug for the
|
|
119
|
+
* injected adapter id. Strips anything that isn't a lowercase letter or
|
|
120
|
+
* digit (turning "Polkadot{.js}" → "polkadot-js"), then prepends the
|
|
121
|
+
* injected Polkadot channel prefix.
|
|
122
|
+
*
|
|
123
|
+
* This is intentionally NOT the wallet-standard-shared `slugify` helper
|
|
124
|
+
* — that helper embeds the `wallet-standard:` scheme which is wrong for
|
|
125
|
+
* the injected channel. The ID convention for injected adapters is
|
|
126
|
+
* `injected:polkadot:<slug>`.
|
|
127
|
+
*/
|
|
128
|
+
const toKebab = (name) => name.trim().toLowerCase().replaceAll(/* @__PURE__ */ new RegExp("[^a-z0-9]+", "gv"), "-").replaceAll(/* @__PURE__ */ new RegExp("^-|-$", "gv"), "");
|
|
129
|
+
const buildPolkadotAccount = (address, chain) => ({
|
|
130
|
+
chain,
|
|
131
|
+
id: `${chain.id}:${address}`,
|
|
132
|
+
walletAddress: address
|
|
133
|
+
});
|
|
134
|
+
/**
|
|
135
|
+
* Wrap a `window.injectedWeb3[name]` provider into a butr
|
|
136
|
+
* `PolkadotAdapter`. The provider is NOT enabled at construction —
|
|
137
|
+
* `enable()` triggers the authorization prompt, so it runs lazily in
|
|
138
|
+
* `connect()`. Before connect, `getAccount` returns null.
|
|
139
|
+
*
|
|
140
|
+
* `id` is `injected:polkadot:<slug>` so consumers can distinguish the
|
|
141
|
+
* injected channel from the Wallet Standard one in their picker.
|
|
142
|
+
*/
|
|
143
|
+
const buildInjectedPolkadotAdapter = (extensionName, displayName, provider) => {
|
|
144
|
+
const capabilities = resolveInjectedPolkadotCapabilities();
|
|
145
|
+
let injected = null;
|
|
146
|
+
let chain = POLKADOT_CHAINS.polkadot;
|
|
147
|
+
const listenersSet = /* @__PURE__ */ new Set();
|
|
148
|
+
const requireInjected = () => {
|
|
149
|
+
if (!injected) throw new Error(`Wallet ${displayName} is not connected`);
|
|
150
|
+
return injected;
|
|
151
|
+
};
|
|
152
|
+
const firstAddress = async () => {
|
|
153
|
+
if (!injected) return null;
|
|
154
|
+
return (await injected.accounts.get())[0]?.address ?? null;
|
|
155
|
+
};
|
|
156
|
+
return {
|
|
157
|
+
capabilities,
|
|
158
|
+
chainPlatform: "polkadot",
|
|
159
|
+
async connect() {
|
|
160
|
+
injected = await provider.enable(DAPP_NAME);
|
|
161
|
+
if ((await injected.accounts.get()).length === 0) throw new Error(`Wallet ${displayName} exposed no accounts`);
|
|
162
|
+
},
|
|
163
|
+
disconnect() {
|
|
164
|
+
injected = null;
|
|
165
|
+
return Promise.resolve();
|
|
166
|
+
},
|
|
167
|
+
async getAccount() {
|
|
168
|
+
const address = await firstAddress();
|
|
169
|
+
return address ? buildPolkadotAccount(address, chain) : null;
|
|
170
|
+
},
|
|
171
|
+
async getAccounts() {
|
|
172
|
+
if (!injected) return [];
|
|
173
|
+
return (await injected.accounts.get()).map((a) => buildPolkadotAccount(a.address, chain));
|
|
174
|
+
},
|
|
175
|
+
getBalance: noRpcBalance,
|
|
176
|
+
async getSigner() {
|
|
177
|
+
const ext = requireInjected();
|
|
178
|
+
const address = await firstAddress();
|
|
179
|
+
if (!address) throw new Error("No connected account");
|
|
180
|
+
return {
|
|
181
|
+
address,
|
|
182
|
+
extension: ext,
|
|
183
|
+
extensionName
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
getTransactionReceipt: noRpcTransactionReceipt,
|
|
187
|
+
icon: sanitizeIcon(GENERIC_POLKADOT_ICON),
|
|
188
|
+
id: `injected:polkadot:${toKebab(extensionName)}`,
|
|
189
|
+
name: displayName,
|
|
190
|
+
sendTx: noRpcSendTx,
|
|
191
|
+
sendTxToChain: noRpcSendTxToChain,
|
|
192
|
+
async signMessage(msg, account) {
|
|
193
|
+
const ext = requireInjected();
|
|
194
|
+
if (!ext.signer.signRaw) throw new Error(`Wallet ${displayName} does not expose signRaw`);
|
|
195
|
+
const address = account?.walletAddress ?? await firstAddress();
|
|
196
|
+
if (!address) throw new Error("No connected account");
|
|
197
|
+
const wrapped = wrapBytes(msg);
|
|
198
|
+
return {
|
|
199
|
+
signature: hexToBytes((await ext.signer.signRaw({
|
|
200
|
+
address,
|
|
201
|
+
data: bytesToHex(wrapped),
|
|
202
|
+
type: "bytes"
|
|
203
|
+
})).signature),
|
|
204
|
+
signedMessage: wrapped
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
subscribe(listener) {
|
|
208
|
+
listenersSet.add(listener);
|
|
209
|
+
let unsubWallet = null;
|
|
210
|
+
if (injected?.accounts.subscribe) unsubWallet = injected.accounts.subscribe((accounts) => {
|
|
211
|
+
if (accounts.length === 0) {
|
|
212
|
+
listener({ type: "disconnected" });
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const built = accounts.map((a) => buildPolkadotAccount(a.address, chain));
|
|
216
|
+
const first = built[0];
|
|
217
|
+
if (first) listener({
|
|
218
|
+
account: first,
|
|
219
|
+
accounts: built,
|
|
220
|
+
type: "accountChanged"
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
return () => {
|
|
224
|
+
listenersSet.delete(listener);
|
|
225
|
+
unsubWallet?.();
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
switchChain(target) {
|
|
229
|
+
if (target.namespace !== "polkadot") return Promise.reject(/* @__PURE__ */ new Error(`Polkadot adapter received non-Polkadot chain "${target.id}". Pass a chain with namespace "polkadot".`));
|
|
230
|
+
chain = target;
|
|
231
|
+
return Promise.resolve();
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/injected/index.ts
|
|
238
|
+
const KNOWN_NAMES = {
|
|
239
|
+
enkrypt: "Enkrypt",
|
|
240
|
+
"nova-wallet": "Nova Wallet",
|
|
241
|
+
"polkadot-js": "Polkadot{.js}",
|
|
242
|
+
"subwallet-js": "SubWallet",
|
|
243
|
+
talisman: "Talisman"
|
|
244
|
+
};
|
|
245
|
+
const displayNameFor = (key) => KNOWN_NAMES[key] ?? key.split(/* @__PURE__ */ new RegExp("[\\-_]", "v")).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
246
|
+
const DEFAULT_POLLS = [250, 750];
|
|
247
|
+
/**
|
|
248
|
+
* Primary Polkadot discovery: enumerate `window.injectedWeb3` keys and
|
|
249
|
+
* emit one `PolkadotAdapter` per extension. Adapters are built WITHOUT
|
|
250
|
+
* calling `enable()` (no prompt at discovery time); `connect()` enables
|
|
251
|
+
* lazily.
|
|
252
|
+
*
|
|
253
|
+
* Extensions inject at different times during page load, so we read
|
|
254
|
+
* immediately and re-check on a short poll schedule, deduping by key.
|
|
255
|
+
*/
|
|
256
|
+
const discoverInjectedPolkadotAdapters = (onAdapter, options = {}) => {
|
|
257
|
+
const polls = options.pollMs ?? DEFAULT_POLLS;
|
|
258
|
+
const seen = /* @__PURE__ */ new Set();
|
|
259
|
+
const timers = [];
|
|
260
|
+
let cancelled = false;
|
|
261
|
+
const scan = () => {
|
|
262
|
+
if (cancelled) return;
|
|
263
|
+
const registry = readInjectedWindow(options.target)?.injectedWeb3;
|
|
264
|
+
if (!registry) return;
|
|
265
|
+
for (const [key, provider] of Object.entries(registry)) {
|
|
266
|
+
if (seen.has(key)) continue;
|
|
267
|
+
seen.add(key);
|
|
268
|
+
onAdapter(buildInjectedPolkadotAdapter(key, displayNameFor(key), provider));
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
scan();
|
|
272
|
+
for (const offset of polls) {
|
|
273
|
+
if (offset === 0) continue;
|
|
274
|
+
timers.push(setTimeout(scan, offset));
|
|
275
|
+
}
|
|
276
|
+
return () => {
|
|
277
|
+
cancelled = true;
|
|
278
|
+
for (const timer of timers) clearTimeout(timer);
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region src/wallet-standard-adapter.ts
|
|
284
|
+
const POLKADOT_PREFIX = "polkadot:";
|
|
285
|
+
const slugify$1 = (name) => slugify("polkadot", name);
|
|
286
|
+
const pickPolkadotChain = (wallet) => wallet.chains.find((c) => c.startsWith(POLKADOT_PREFIX)) ?? null;
|
|
287
|
+
const buildChain = (chainId, walletName) => ({
|
|
288
|
+
id: chainId,
|
|
289
|
+
name: walletName,
|
|
290
|
+
namespace: "polkadot",
|
|
291
|
+
reference: chainId.slice(9)
|
|
292
|
+
});
|
|
293
|
+
const buildWsAccount = (address, chain) => buildAccount(address, chain);
|
|
294
|
+
/**
|
|
295
|
+
* Adapt a Wallet Standard wallet advertising `polkadot:*` features into a
|
|
296
|
+
* butr `WalletAdapter`. Returns `null` for wallets that don't advertise a
|
|
297
|
+
* polkadot chain or `standard:connect`. butr ships no RPC, so
|
|
298
|
+
* sendTx/getBalance/getTransactionReceipt are placeholders; transaction
|
|
299
|
+
* signing goes through `getSigner()` (returns the Wallet Standard wallet).
|
|
300
|
+
*/
|
|
301
|
+
const buildPolkadotWalletStandardAdapter = (wallet, registerDisconnector) => {
|
|
302
|
+
const chainId = pickPolkadotChain(wallet);
|
|
303
|
+
if (!chainId) return null;
|
|
304
|
+
const connect = getFeature(wallet, "standard:connect");
|
|
305
|
+
if (!connect) return null;
|
|
306
|
+
const disconnect = getFeature(wallet, "standard:disconnect");
|
|
307
|
+
const events = getFeature(wallet, "standard:events");
|
|
308
|
+
const signMessage = getFeature(wallet, "polkadot:signMessage");
|
|
309
|
+
let currentChainId = chainId;
|
|
310
|
+
const currentChain = () => buildChain(currentChainId, wallet.name);
|
|
311
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
312
|
+
const notifyAccountChanged = () => {
|
|
313
|
+
if (wallet.accounts.length === 0) return;
|
|
314
|
+
const chain = currentChain();
|
|
315
|
+
const built = wallet.accounts.map((a) => buildWsAccount(a.address, chain));
|
|
316
|
+
const first = built[0];
|
|
317
|
+
if (!first) 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" });
|
|
326
|
+
});
|
|
327
|
+
return {
|
|
328
|
+
capabilities: resolveWalletStandardPolkadotCapabilities({
|
|
329
|
+
chainCount: wallet.chains.filter((c) => c.startsWith(POLKADOT_PREFIX)).length,
|
|
330
|
+
features: {
|
|
331
|
+
events: Boolean(events),
|
|
332
|
+
signMessage: Boolean(signMessage)
|
|
333
|
+
}
|
|
334
|
+
}),
|
|
335
|
+
chainPlatform: "polkadot",
|
|
336
|
+
async connect(opts) {
|
|
337
|
+
await connect.connect(opts?.silent ? { silent: true } : void 0);
|
|
338
|
+
},
|
|
339
|
+
async disconnect() {
|
|
340
|
+
if (disconnect) 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 ? buildWsAccount(address, currentChain()) : null);
|
|
349
|
+
},
|
|
350
|
+
getAccounts() {
|
|
351
|
+
const chain = currentChain();
|
|
352
|
+
return Promise.resolve(wallet.accounts.map((a) => buildWsAccount(a.address, chain)));
|
|
353
|
+
},
|
|
354
|
+
getBalance: noRpcBalance,
|
|
355
|
+
getSigner() {
|
|
356
|
+
return Promise.resolve(wallet);
|
|
357
|
+
},
|
|
358
|
+
getTransactionReceipt: noRpcTransactionReceipt,
|
|
359
|
+
icon: sanitizeIcon(wallet.icon),
|
|
360
|
+
id: slugify$1(wallet.name),
|
|
361
|
+
name: wallet.name,
|
|
362
|
+
sendTx: noRpcSendTx,
|
|
363
|
+
sendTxToChain: noRpcSendTxToChain,
|
|
364
|
+
async signMessage(msg, account) {
|
|
365
|
+
if (!signMessage) throw new Error(`Wallet ${wallet.name} does not advertise polkadot:signMessage`);
|
|
366
|
+
const wsAccount = account ? pickAccountByAddress(wallet.accounts, account.walletAddress) : wallet.accounts[0] ?? null;
|
|
367
|
+
if (!wsAccount) throw new Error("No connected account");
|
|
368
|
+
const output = await signMessage.signMessage({
|
|
369
|
+
account: wsAccount,
|
|
370
|
+
message: msg
|
|
371
|
+
});
|
|
372
|
+
return {
|
|
373
|
+
signature: output.signature,
|
|
374
|
+
signedMessage: output.signedMessage ?? msg
|
|
375
|
+
};
|
|
376
|
+
},
|
|
377
|
+
subscribe(listener) {
|
|
378
|
+
listeners.add(listener);
|
|
379
|
+
let unsubWallet = null;
|
|
380
|
+
if (events) {
|
|
381
|
+
const unsub = events.on("change", (changes) => {
|
|
382
|
+
if (changes.accounts) {
|
|
383
|
+
if (changes.accounts.length === 0) {
|
|
384
|
+
listener({ type: "disconnected" });
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
const chain = currentChain();
|
|
388
|
+
const built = changes.accounts.map((a) => buildWsAccount(a.address, chain));
|
|
389
|
+
const first = built[0];
|
|
390
|
+
if (first) listener({
|
|
391
|
+
account: first,
|
|
392
|
+
accounts: built,
|
|
393
|
+
type: "accountChanged"
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
unsubWallet = () => unsub();
|
|
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
|
+
}
|
|
411
|
+
};
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
//#endregion
|
|
415
|
+
//#region src/wallet-standard.ts
|
|
416
|
+
/**
|
|
417
|
+
* Subscribe to Wallet Standard announcements and emit adapters for
|
|
418
|
+
* wallets advertising `polkadot:*` features (Talisman, SubWallet). Used
|
|
419
|
+
* as the FALLBACK channel — see `polkadotDiscoverer`. Requires the
|
|
420
|
+
* optional `@wallet-standard/app` peer dep; absent → no-op.
|
|
421
|
+
*/
|
|
422
|
+
const discoverPolkadotWalletStandardAdapters = (onAdapter) => discoverWalletStandard(onAdapter, (wallet, registerDisconnector) => buildPolkadotWalletStandardAdapter(wallet, registerDisconnector));
|
|
423
|
+
|
|
424
|
+
//#endregion
|
|
425
|
+
//#region src/discoverer.ts
|
|
426
|
+
/**
|
|
427
|
+
* Polkadot's `PlatformDiscoverer`. Inverts the Bitcoin layout:
|
|
428
|
+
* - PRIMARY (`subscribe`) is injectedWeb3 — the dominant, broadest
|
|
429
|
+
* Polkadot standard (polkadot-js, Talisman, SubWallet, Nova, Enkrypt).
|
|
430
|
+
* - FALLBACK is Wallet Standard `polkadot:*`. It defers when the primary
|
|
431
|
+
* channel already produced an adapter for the session
|
|
432
|
+
* (`hasAnyPrimaryAdapter`). Since Wallet Standard support is always
|
|
433
|
+
* additive on Polkadot today (Talisman/SubWallet expose both), the
|
|
434
|
+
* discovery-bus also dedups overlaps and the defer prevents
|
|
435
|
+
* double-listing.
|
|
436
|
+
*/
|
|
437
|
+
const polkadotDiscoverer = {
|
|
438
|
+
fallback: { subscribe: (onAdapter, opts) => {
|
|
439
|
+
if (opts.hasAnyPrimaryAdapter()) return () => void 0;
|
|
440
|
+
return discoverPolkadotWalletStandardAdapters(onAdapter);
|
|
441
|
+
} },
|
|
442
|
+
platform: "polkadot",
|
|
443
|
+
subscribe: discoverInjectedPolkadotAdapters
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
//#endregion
|
|
447
|
+
export { POLKADOT_CHAINS, POLKADOT_CHAINS_LIST, buildInjectedPolkadotAdapter, buildPolkadotWalletStandardAdapter, discoverInjectedPolkadotAdapters, discoverPolkadotWalletStandardAdapters, polkadotDiscoverer, resolveInjectedPolkadotCapabilities, resolveWalletStandardPolkadotCapabilities };
|
|
2
448
|
//# sourceMappingURL=index.js.map
|
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// butr ships no RPC: getBalance / getTransactionReceipt / sendTransaction\n// are always false on Polkadot. signTransaction is false too — building a\n// Substrate extrinsic needs chain metadata, so transaction signing goes\n// through getSigner() (consumer drives polkadot-api). requestAccounts is\n// false: extensions manage account exposure in their own UI.\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\n// Neutral, chain-agnostic placeholder. The registry spans DOT/KSM/WND/PAS\n// with different symbols and decimals, so a hardcoded \"DOT\"/10 would be\n// wrong for most of them. Consumers read real balances via polkadot-api.\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","// Generic Polkadot mark (pink dot), data-URI so the connector ships no\n// asset files. Mirrors @usebutr/bitcoin's GENERIC_BITCOIN_ICON approach.\nconst 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\n// `<Bytes>` / `</Bytes>` wrapper polkadot-js, Talisman, and SubWallet add\n// around raw messages before signing (prevents signed messages from being\n// replayed as transaction payloads). Verifiers must check signatures\n// against the wrapped bytes, which is why butr returns them as\n// `signedMessage`.\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 bytesToHex = (bytes: Uint8Array): string => {\n let hex = \"0x\";\n for (const byte of bytes) {\n hex += byte.toString(16).padStart(2, \"0\");\n }\n return hex;\n};\n\nconst hexToBytes = (hex: string): Uint8Array => {\n const clean = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const out = new Uint8Array(clean.length / 2);\n for (let i = 0; i < out.length; i += 1) {\n out[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n};\n\nconst readInjectedWindow = (target?: InjectedWindow | null): InjectedWindow | null => {\n if (target !== undefined) {\n return target;\n }\n return typeof window === \"undefined\" ? null : (window as unknown as InjectedWindow);\n};\n\nexport type { Injected, InjectedAccount, InjectedSigner, InjectedWindow, InjectedWindowProvider };\nexport { bytesToHex, hexToBytes, 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) {\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) {\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 ? buildPolkadotAccount(address, chain) : null;\n },\n\n async getAccounts() {\n if (!injected) {\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) {\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) {\n throw new Error(`Wallet ${displayName} does not expose signRaw`);\n }\n const address = account?.walletAddress ?? (await firstAddress());\n if (!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) {\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 // Substrate accounts are chain-agnostic; switching is local state\n // that tells consumers which chain context to target.\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\n// Display-name overrides for known registry keys. Unknown keys fall back\n// to a title-cased version of the key.\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 { Account, 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\nconst buildWsAccount = (address: string, chain: ChainBase): Account => buildAccount(address, chain);\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) {\n return null;\n }\n const connect = getFeature<StandardConnectFeature>(wallet, \"standard:connect\");\n if (!connect) {\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) => buildWsAccount(a.address, chain));\n const first = built[0];\n if (!first) {\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 ? { silent: true } : undefined);\n },\n\n async disconnect() {\n if (disconnect) {\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 ? buildWsAccount(address, currentChain()) : null);\n },\n\n getAccounts() {\n const chain = currentChain();\n return Promise.resolve(wallet.accounts.map((a) => buildWsAccount(a.address, chain)));\n },\n\n getBalance: noRpcBalance,\n\n getSigner() {\n return Promise.resolve(wallet);\n },\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) {\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] ?? null);\n if (!wsAccount) {\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) {\n const unsub = events.on(\"change\", (changes) => {\n if (changes.accounts) {\n if (changes.accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const chain = currentChain();\n const built = changes.accounts.map((a) => buildWsAccount(a.address, chain));\n const first = built[0];\n if (first) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n }\n });\n unsubWallet = () => unsub();\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/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// butr ships no RPC: getBalance / getTransactionReceipt / sendTransaction\n// are always false on Polkadot. signTransaction is false too — building a\n// Substrate extrinsic needs chain metadata, so transaction signing goes\n// through getSigner() (consumer drives polkadot-api). requestAccounts is\n// false: extensions manage account exposure in their own UI.\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\n// Neutral, chain-agnostic placeholder. The registry spans DOT/KSM/WND/PAS\n// with different symbols and decimals, so a hardcoded \"DOT\"/10 would be\n// wrong for most of them. Consumers read real balances via polkadot-api.\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","// Generic Polkadot mark (pink dot), data-URI so the connector ships no\n// asset files. Mirrors @usebutr/bitcoin's GENERIC_BITCOIN_ICON approach.\nconst 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\n// `<Bytes>` / `</Bytes>` wrapper polkadot-js, Talisman, and SubWallet add\n// around raw messages before signing (prevents signed messages from being\n// replayed as transaction payloads). Verifiers must check signatures\n// against the wrapped bytes, which is why butr returns them as\n// `signedMessage`.\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 return typeof window === \"undefined\" ? null : (window as unknown as InjectedWindow);\n};\n\nexport type { Injected, InjectedAccount, InjectedSigner, InjectedWindow, InjectedWindowProvider };\n// Polkadot uses 0x-prefixed hex; alias the shared prefixed variant to the\n// existing local name so internal callers stay unchanged.\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) {\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) {\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 ? buildPolkadotAccount(address, chain) : null;\n },\n\n async getAccounts() {\n if (!injected) {\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) {\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) {\n throw new Error(`Wallet ${displayName} does not expose signRaw`);\n }\n const address = account?.walletAddress ?? (await firstAddress());\n if (!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) {\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 // Substrate accounts are chain-agnostic; switching is local state\n // that tells consumers which chain context to target.\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\n// Display-name overrides for known registry keys. Unknown keys fall back\n// to a title-cased version of the key.\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 { Account, 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\nconst buildWsAccount = (address: string, chain: ChainBase): Account => buildAccount(address, chain);\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) {\n return null;\n }\n const connect = getFeature<StandardConnectFeature>(wallet, \"standard:connect\");\n if (!connect) {\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) => buildWsAccount(a.address, chain));\n const first = built[0];\n if (!first) {\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 ? { silent: true } : undefined);\n },\n\n async disconnect() {\n if (disconnect) {\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 ? buildWsAccount(address, currentChain()) : null);\n },\n\n getAccounts() {\n const chain = currentChain();\n return Promise.resolve(wallet.accounts.map((a) => buildWsAccount(a.address, chain)));\n },\n\n getBalance: noRpcBalance,\n\n getSigner() {\n return Promise.resolve(wallet);\n },\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) {\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] ?? null);\n if (!wsAccount) {\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) {\n const unsub = events.on(\"change\", (changes) => {\n if (changes.accounts) {\n if (changes.accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const chain = currentChain();\n const built = changes.accounts.map((a) => buildWsAccount(a.address, chain));\n const first = built[0];\n if (first) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n }\n });\n unsubWallet = () => unsub();\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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebutr/polkadot",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "injectedWeb3 + Wallet Standard adapter for butr (Polkadot/Substrate).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Pedro Filho <pedro@filho.me>",
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@usebutr/
|
|
29
|
-
"@usebutr/
|
|
28
|
+
"@usebutr/wallet-standard-shared": "0.2.5",
|
|
29
|
+
"@usebutr/core": "0.4.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@wallet-standard/app": "^1.1.
|
|
32
|
+
"@wallet-standard/app": "^1.1.1",
|
|
33
33
|
"typescript": "^6.0.3",
|
|
34
|
-
"vitest": "^4.1.
|
|
34
|
+
"vitest": "^4.1.9",
|
|
35
35
|
"@repo/config-vitest": "0.0.0",
|
|
36
36
|
"@repo/typescript-config": "0.0.0"
|
|
37
37
|
},
|