@leather.io/provider 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/LICENSE +21 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +368 -0
- package/dist/index.js.map +1 -0
- package/dist/injected-provider.d.ts +7 -0
- package/dist/injected-provider.js +378 -0
- package/dist/injected-provider.js.map +1 -0
- package/dist/mobile.d.ts +2 -0
- package/dist/mobile.js +378 -0
- package/dist/mobile.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
export default ({branch, commitSha, version}) => `// src/add-leather-to-providers.ts
|
|
2
|
+
function addLeatherToProviders() {
|
|
3
|
+
const win = window;
|
|
4
|
+
if (!win.btc_providers) win.btc_providers = [];
|
|
5
|
+
win.btc_providers.push({
|
|
6
|
+
id: "LeatherProvider",
|
|
7
|
+
name: "Leather",
|
|
8
|
+
icon: "data:image/svg;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYuODM4NyIgZmlsbD0iIzEyMTAwRiIvPgo8cGF0aCBkPSJNNzQuOTE3MSA1Mi43MTE0QzgyLjQ3NjYgNTEuNTQwOCA5My40MDg3IDQzLjU4MDQgOTMuNDA4NyAzNy4zNzYxQzkzLjQwODcgMzUuNTAzMSA5MS44OTY4IDM0LjIxNTQgODkuNjg3MSAzNC4yMTU0Qzg1LjUwMDQgMzQuMjE1NCA3OC40MDYxIDQwLjUzNjggNzQuOTE3MSA1Mi43MTE0Wk0zOS45MTEgODMuNDk5MUMzMC4wMjU2IDgzLjQ5OTEgMjkuMjExNSA5My4zMzI0IDM5LjA5NjkgOTMuMzMyNEM0My41MTYzIDkzLjMzMjQgNDguODY2MSA5MS41NzY0IDUxLjY1NzMgODguNDE1N0M0Ny41ODY4IDg0LjkwMzggNDQuMjE0MSA4My40OTkxIDM5LjkxMSA4My40OTkxWk0xMDIuODI5IDc5LjI4NDhDMTAzLjQxIDk1Ljc5MDcgOTUuMDM2OSAxMDUuMDM5IDgwLjg0ODQgMTA1LjAzOUM3Mi40NzQ4IDEwNS4wMzkgNjguMjg4MSAxMDEuODc4IDU5LjMzMyA5Ni4wMjQ4QzU0LjY4MSAxMDEuMTc2IDQ1Ljg0MjMgMTA1LjAzOSAzOC41MTU0IDEwNS4wMzlDMTMuMjc4NSAxMDUuMDM5IDE0LjMyNTIgNzIuODQ2MyA0MC4wMjczIDcyLjg0NjNDNDUuMzc3MSA3Mi44NDYzIDQ5LjkxMjggNzQuMjUxMSA1NS43Mjc3IDc3Ljg4TDU5LjU2NTYgNjQuNDE3N0M0My43NDg5IDYwLjA4NjQgMzUuODQwNSA0Ny45MTE4IDQzLjYzMjYgMzAuNDY5M0g1Ni4xOTI5QzQ5LjIxNSA0Mi4wNTg2IDUzLjk4MzIgNTEuNjU3OCA2Mi44MjIgNTIuNzExNEM2Ny41OTAzIDM1LjczNzIgNzcuODI0NiAyMi41MDkgOTEuNDMxNiAyMi41MDlDOTkuMTA3NCAyMi41MDkgMTA1LjE1NSAyNy41NDI4IDEwNS4xNTUgMzYuNjczN0MxMDUuMTU1IDUxLjMwNjYgODYuMDgxOSA2My4yNDcxIDcxLjY2MDcgNjQuNDE3N0w2NS43Mjk1IDg1LjM3MjFDNzIuNDc0OCA5My4yMTUzIDkxLjE5OSAxMDAuODI0IDkxLjE5OSA3OS4yODQ4SDEwMi44MjlaIiBmaWxsPSIjRjdGNUYzIi8+Cjwvc3ZnPgo=",
|
|
9
|
+
webUrl: "https://leather.io",
|
|
10
|
+
chromeWebStoreUrl: "https://chromewebstore.google.com/detail/leather/ldinpeekobnhjjdofggfgjlcehhmanlj",
|
|
11
|
+
methods: [
|
|
12
|
+
"open",
|
|
13
|
+
"getInfo",
|
|
14
|
+
"supportedMethods",
|
|
15
|
+
"openSwap",
|
|
16
|
+
"getAddresses",
|
|
17
|
+
"stx_updateProfile",
|
|
18
|
+
"stx_signMessage",
|
|
19
|
+
"stx_transferStx",
|
|
20
|
+
"stx_transferSip10Ft",
|
|
21
|
+
"stx_signTransaction",
|
|
22
|
+
"stx_signStructuredMessage",
|
|
23
|
+
"stx_getAddresses",
|
|
24
|
+
"stx_deployContract",
|
|
25
|
+
"stx_callContract",
|
|
26
|
+
"signPsbt",
|
|
27
|
+
"signMessage",
|
|
28
|
+
"sendTransfer"
|
|
29
|
+
// Better to import a type than a variable from @leather.io/rpc to save a lot of space in the injected provider script
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/legacy-requests.ts
|
|
35
|
+
var MESSAGE_SOURCE = "stacks-wallet";
|
|
36
|
+
function isValidEvent(event, method) {
|
|
37
|
+
const { data } = event;
|
|
38
|
+
const correctSource = data.source === MESSAGE_SOURCE;
|
|
39
|
+
const correctMethod = data.method === method;
|
|
40
|
+
return correctSource && correctMethod && !!data.payload;
|
|
41
|
+
}
|
|
42
|
+
async function callAndReceive(methodName, opts = {}) {
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const timeout = setTimeout(() => {
|
|
45
|
+
reject("Unable to get response from Blockstack extension");
|
|
46
|
+
}, 1e3);
|
|
47
|
+
function waitForResponse(event) {
|
|
48
|
+
if (event.data.source === "blockstack-extension" && event.data.method === \`\${methodName}Response\`) {
|
|
49
|
+
clearTimeout(timeout);
|
|
50
|
+
window.removeEventListener("message", waitForResponse);
|
|
51
|
+
resolve(event.data);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
window.addEventListener("message", waitForResponse);
|
|
55
|
+
window.postMessage(
|
|
56
|
+
{
|
|
57
|
+
method: methodName,
|
|
58
|
+
source: "blockstack-app",
|
|
59
|
+
...opts
|
|
60
|
+
},
|
|
61
|
+
window.location.origin
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function placeholderLegacyRequests() {
|
|
66
|
+
return {
|
|
67
|
+
getURL: () => {
|
|
68
|
+
throw new Error("This function i deprecated");
|
|
69
|
+
},
|
|
70
|
+
structuredDataSignatureRequest: () => {
|
|
71
|
+
throw new Error("This function is deprecated");
|
|
72
|
+
},
|
|
73
|
+
signatureRequest: () => {
|
|
74
|
+
throw new Error("This function is deprecated");
|
|
75
|
+
},
|
|
76
|
+
authenticationRequest: () => {
|
|
77
|
+
throw new Error("This function is deprecated");
|
|
78
|
+
},
|
|
79
|
+
transactionRequest: () => {
|
|
80
|
+
throw new Error("This function is deprecated");
|
|
81
|
+
},
|
|
82
|
+
psbtRequest: () => {
|
|
83
|
+
throw new Error("This function is deprecated");
|
|
84
|
+
},
|
|
85
|
+
profileUpdateRequest: () => {
|
|
86
|
+
throw new Error("This function is deprecated");
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function legacyRequests() {
|
|
91
|
+
return {
|
|
92
|
+
getURL: async () => {
|
|
93
|
+
const { url } = await callAndReceive("getURL");
|
|
94
|
+
return url;
|
|
95
|
+
},
|
|
96
|
+
structuredDataSignatureRequest: async (signatureRequest) => {
|
|
97
|
+
const event = new CustomEvent(
|
|
98
|
+
"hiroWalletStructuredDataSignatureRequest" /* structuredDataSignatureRequest */,
|
|
99
|
+
{
|
|
100
|
+
detail: { signatureRequest }
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
document.dispatchEvent(event);
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
function handleMessage(event2) {
|
|
106
|
+
if (!isValidEvent(event2, "hiroWalletSignatureResponse" /* signatureResponse */)) return;
|
|
107
|
+
if (event2.data.payload?.signatureRequest !== signatureRequest) return;
|
|
108
|
+
window.removeEventListener("message", handleMessage);
|
|
109
|
+
if (event2.data.payload.signatureResponse === "cancel") {
|
|
110
|
+
reject(event2.data.payload.signatureResponse);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (typeof event2.data.payload.signatureResponse !== "string") {
|
|
114
|
+
resolve(event2.data.payload.signatureResponse);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
window.addEventListener("message", handleMessage);
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
signatureRequest: async (signatureRequest) => {
|
|
121
|
+
const event = new CustomEvent("hiroWalletSignatureRequest" /* signatureRequest */, {
|
|
122
|
+
detail: { signatureRequest }
|
|
123
|
+
});
|
|
124
|
+
document.dispatchEvent(event);
|
|
125
|
+
return new Promise((resolve, reject) => {
|
|
126
|
+
function handleMessage(event2) {
|
|
127
|
+
if (!isValidEvent(event2, "hiroWalletSignatureResponse" /* signatureResponse */)) return;
|
|
128
|
+
if (event2.data.payload?.signatureRequest !== signatureRequest) return;
|
|
129
|
+
window.removeEventListener("message", handleMessage);
|
|
130
|
+
if (event2.data.payload.signatureResponse === "cancel") {
|
|
131
|
+
reject(event2.data.payload.signatureResponse);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (typeof event2.data.payload.signatureResponse !== "string") {
|
|
135
|
+
resolve(event2.data.payload.signatureResponse);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
window.addEventListener("message", handleMessage);
|
|
139
|
+
});
|
|
140
|
+
},
|
|
141
|
+
authenticationRequest: async (authenticationRequest) => {
|
|
142
|
+
console.warn(\`
|
|
143
|
+
WARNING: Legacy Leather request detected
|
|
144
|
+
|
|
145
|
+
Leather now uses an RPC-style API, that can be used directly,
|
|
146
|
+
rather than through libraries such as Stacks Connect. For example,
|
|
147
|
+
to get a user's addresses, you should use the
|
|
148
|
+
LeatherProvider.request('getAddresses') method.
|
|
149
|
+
|
|
150
|
+
See our docs for more information https://leather.gitbook.io/
|
|
151
|
+
\`);
|
|
152
|
+
const event = new CustomEvent(
|
|
153
|
+
"hiroWalletStacksAuthenticationRequest" /* authenticationRequest */,
|
|
154
|
+
{
|
|
155
|
+
detail: { authenticationRequest }
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
document.dispatchEvent(event);
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
function handleMessage(event2) {
|
|
161
|
+
if (!isValidEvent(event2, "hiroWalletAuthenticationResponse" /* authenticationResponse */)) return;
|
|
162
|
+
if (event2.data.payload?.authenticationRequest !== authenticationRequest) return;
|
|
163
|
+
window.removeEventListener("message", handleMessage);
|
|
164
|
+
if (event2.data.payload.authenticationResponse === "cancel") {
|
|
165
|
+
reject(event2.data.payload.authenticationResponse);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
resolve(event2.data.payload.authenticationResponse);
|
|
169
|
+
}
|
|
170
|
+
window.addEventListener("message", handleMessage);
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
transactionRequest: async (transactionRequest) => {
|
|
174
|
+
const event = new CustomEvent(
|
|
175
|
+
"hiroWalletStacksTransactionRequest" /* transactionRequest */,
|
|
176
|
+
{
|
|
177
|
+
detail: { transactionRequest }
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
document.dispatchEvent(event);
|
|
181
|
+
return new Promise((resolve, reject) => {
|
|
182
|
+
function handleMessage(event2) {
|
|
183
|
+
if (!isValidEvent(event2, "hiroWalletTransactionResponse" /* transactionResponse */)) return;
|
|
184
|
+
if (event2.data.payload?.transactionRequest !== transactionRequest) return;
|
|
185
|
+
window.removeEventListener("message", handleMessage);
|
|
186
|
+
if (event2.data.payload.transactionResponse === "cancel") {
|
|
187
|
+
reject(event2.data.payload.transactionResponse);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (typeof event2.data.payload.transactionResponse !== "string") {
|
|
191
|
+
resolve(event2.data.payload.transactionResponse);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
window.addEventListener("message", handleMessage);
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
psbtRequest: async (psbtRequest) => {
|
|
198
|
+
const event = new CustomEvent("hiroWalletPsbtRequest" /* psbtRequest */, {
|
|
199
|
+
detail: { psbtRequest }
|
|
200
|
+
});
|
|
201
|
+
document.dispatchEvent(event);
|
|
202
|
+
return new Promise((resolve, reject) => {
|
|
203
|
+
function handleMessage(event2) {
|
|
204
|
+
if (!isValidEvent(event2, "hiroWalletPsbtResponse" /* psbtResponse */)) return;
|
|
205
|
+
if (event2.data.payload?.psbtRequest !== psbtRequest) return;
|
|
206
|
+
window.removeEventListener("message", handleMessage);
|
|
207
|
+
if (event2.data.payload.psbtResponse === "cancel") {
|
|
208
|
+
reject(event2.data.payload.psbtResponse);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (typeof event2.data.payload.psbtResponse !== "string") {
|
|
212
|
+
resolve(event2.data.payload.psbtResponse);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
window.addEventListener("message", handleMessage);
|
|
216
|
+
});
|
|
217
|
+
},
|
|
218
|
+
profileUpdateRequest: async (profileUpdateRequest) => {
|
|
219
|
+
const event = new CustomEvent(
|
|
220
|
+
"hiroWalletProfileUpdateRequest" /* profileUpdateRequest */,
|
|
221
|
+
{
|
|
222
|
+
detail: { profileUpdateRequest }
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
document.dispatchEvent(event);
|
|
226
|
+
return new Promise((resolve, reject) => {
|
|
227
|
+
function handleMessage(event2) {
|
|
228
|
+
if (!isValidEvent(event2, "hiroWalletProfileUpdateResponse" /* profileUpdateResponse */)) return;
|
|
229
|
+
if (event2.data.payload?.profileUpdateRequest !== profileUpdateRequest) return;
|
|
230
|
+
window.removeEventListener("message", handleMessage);
|
|
231
|
+
if (event2.data.payload.profileUpdateResponse === "cancel") {
|
|
232
|
+
reject(event2.data.payload.profileUpdateResponse);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (typeof event2.data.payload.profileUpdateResponse !== "string") {
|
|
236
|
+
resolve(event2.data.payload.profileUpdateResponse);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
window.addEventListener("message", handleMessage);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function getLegacyRequests(platform) {
|
|
245
|
+
switch (platform) {
|
|
246
|
+
case "extension":
|
|
247
|
+
return legacyRequests();
|
|
248
|
+
case "mobile":
|
|
249
|
+
default:
|
|
250
|
+
return placeholderLegacyRequests();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// src/index.ts
|
|
255
|
+
function initInpageProvider({ onDispatch, env }) {
|
|
256
|
+
addLeatherToProviders();
|
|
257
|
+
const provider = {
|
|
258
|
+
isLeather: true,
|
|
259
|
+
...getLegacyRequests(env.platform),
|
|
260
|
+
getProductInfo() {
|
|
261
|
+
return {
|
|
262
|
+
version: env.version,
|
|
263
|
+
name: "Leather",
|
|
264
|
+
meta: {
|
|
265
|
+
tag: env.branch,
|
|
266
|
+
commit: env.commitSha
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
request(method, params) {
|
|
271
|
+
const id = crypto.randomUUID();
|
|
272
|
+
const rpcRequest = {
|
|
273
|
+
jsonrpc: "2.0",
|
|
274
|
+
id,
|
|
275
|
+
method,
|
|
276
|
+
params: params ?? {}
|
|
277
|
+
};
|
|
278
|
+
onDispatch(rpcRequest);
|
|
279
|
+
return new Promise((resolve, reject) => {
|
|
280
|
+
function handleMessage(event) {
|
|
281
|
+
const response = typeof event.data === "object" ? event.data : JSON.parse(event.data);
|
|
282
|
+
if (response.id !== id) return;
|
|
283
|
+
window.removeEventListener("message", handleMessage);
|
|
284
|
+
if ("error" in response) return reject(response);
|
|
285
|
+
return resolve(response);
|
|
286
|
+
}
|
|
287
|
+
window.addEventListener("message", handleMessage);
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
function consoleDeprecationNotice(text) {
|
|
292
|
+
console.warn(\`Deprecation warning: \${text}\`);
|
|
293
|
+
}
|
|
294
|
+
function warnAboutDeprecatedProvider(legacyProvider) {
|
|
295
|
+
return Object.fromEntries(
|
|
296
|
+
Object.entries(legacyProvider).map(([key, value]) => {
|
|
297
|
+
if (typeof value === "function") {
|
|
298
|
+
return [
|
|
299
|
+
key,
|
|
300
|
+
(...args) => {
|
|
301
|
+
switch (key) {
|
|
302
|
+
case "authenticationRequest":
|
|
303
|
+
consoleDeprecationNotice(
|
|
304
|
+
\`Use LeatherProvider.request('getAddresses') instead, see docs https://leather.gitbook.io/developers/bitcoin/connect-users/get-addresses\`
|
|
305
|
+
);
|
|
306
|
+
break;
|
|
307
|
+
case "psbtRequest":
|
|
308
|
+
consoleDeprecationNotice(
|
|
309
|
+
\`Use LeatherProvider.request('signPsbt') instead, see docs https://leather.gitbook.io/developers/bitcoin/sign-transactions/partially-signed-bitcoin-transactions-psbts\`
|
|
310
|
+
);
|
|
311
|
+
break;
|
|
312
|
+
case "structuredDataSignatureRequest":
|
|
313
|
+
case "signatureRequest":
|
|
314
|
+
consoleDeprecationNotice(
|
|
315
|
+
\`Use LeatherProvider.request('stx_signMessage') instead\`
|
|
316
|
+
);
|
|
317
|
+
break;
|
|
318
|
+
default:
|
|
319
|
+
consoleDeprecationNotice(
|
|
320
|
+
"The provider object is deprecated. Use \`LeatherProvider\` instead"
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
return value(...args);
|
|
324
|
+
}
|
|
325
|
+
];
|
|
326
|
+
}
|
|
327
|
+
return [key, value];
|
|
328
|
+
})
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
try {
|
|
332
|
+
Object.defineProperty(window, "StacksProvider", {
|
|
333
|
+
get: () => warnAboutDeprecatedProvider(provider),
|
|
334
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
335
|
+
set: () => {
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
} catch {
|
|
339
|
+
console.log("Unable to set StacksProvider");
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
Object.defineProperty(window, "HiroWalletProvider", {
|
|
343
|
+
get: () => warnAboutDeprecatedProvider(provider),
|
|
344
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
345
|
+
set: () => {
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
} catch {
|
|
349
|
+
console.log("Unable to set HiroWalletProvider");
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
Object.defineProperty(window, "LeatherProvider", {
|
|
353
|
+
get: () => provider,
|
|
354
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
355
|
+
set: () => {
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
} catch {
|
|
359
|
+
console.warn("Unable to set LeatherProvider");
|
|
360
|
+
}
|
|
361
|
+
if (typeof window.btc === "undefined") {
|
|
362
|
+
window.btc = warnAboutDeprecatedProvider(provider);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/mobile.ts
|
|
367
|
+
initInpageProvider({
|
|
368
|
+
onDispatch(rpcRequest) {
|
|
369
|
+
window.ReactNativeWebView.postMessage(JSON.stringify(rpcRequest));
|
|
370
|
+
},
|
|
371
|
+
env: {
|
|
372
|
+
platform: "mobile",
|
|
373
|
+
branch: "${branch}",
|
|
374
|
+
commitSha: "${commitSha}",
|
|
375
|
+
version: "${version}"
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
//# sourceMappingURL=mobile.js.map`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/injected-provider.ts"],"sourcesContent":["// placeholder for creating injected-provider.d.ts for mobile\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport default (_: { branch: string; commitSha: string; version: string }) => '';\n"],"mappings":";AAEA,IAAO,4BAAQ,CAAC,MAA8D;","names":[]}
|
package/dist/mobile.d.ts
ADDED