@defdone/annon 0.0.0-stage → 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/CLI.md +378 -0
  3. package/LICENSE +201 -0
  4. package/NOTICE +7 -0
  5. package/README.md +591 -2
  6. package/dist/api/annon-types.d.ts +108 -0
  7. package/dist/api/annon-types.js +2 -0
  8. package/dist/api/annon.d.ts +117 -0
  9. package/dist/api/annon.js +1152 -0
  10. package/dist/api/hosted-record.d.ts +13 -0
  11. package/dist/api/hosted-record.js +149 -0
  12. package/dist/api/sharing-types.d.ts +109 -0
  13. package/dist/api/sharing-types.js +1 -0
  14. package/dist/api/sharing.d.ts +36 -0
  15. package/dist/api/sharing.js +879 -0
  16. package/dist/browser/download.d.ts +19 -0
  17. package/dist/browser/download.js +52 -0
  18. package/dist/browser/index.d.ts +23 -0
  19. package/dist/browser/index.js +22 -0
  20. package/dist/browser/login-bundle.js +151 -0
  21. package/dist/browser/login.d.ts +1 -0
  22. package/dist/browser/login.js +216 -0
  23. package/dist/browser/purchase-bundle.js +84 -0
  24. package/dist/browser/purchases.d.ts +98 -0
  25. package/dist/browser/purchases.js +735 -0
  26. package/dist/browser/record.d.ts +55 -0
  27. package/dist/browser/record.js +16 -0
  28. package/dist/browser/selling.d.ts +146 -0
  29. package/dist/browser/selling.js +418 -0
  30. package/dist/browser/wallets.d.ts +53 -0
  31. package/dist/browser/wallets.js +286 -0
  32. package/dist/bytes.d.ts +4 -0
  33. package/dist/bytes.js +16 -0
  34. package/dist/download/download.d.ts +59 -0
  35. package/dist/download/download.js +384 -0
  36. package/dist/download/host.d.ts +56 -0
  37. package/dist/download/host.js +161 -0
  38. package/dist/download/http.d.ts +23 -0
  39. package/dist/download/http.js +87 -0
  40. package/dist/download/proof.d.ts +20 -0
  41. package/dist/download/proof.js +79 -0
  42. package/dist/download/upload.d.ts +130 -0
  43. package/dist/download/upload.js +408 -0
  44. package/dist/envelope/evm.d.ts +4 -0
  45. package/dist/envelope/evm.js +32 -0
  46. package/dist/envelope/pay2.d.ts +176 -0
  47. package/dist/envelope/pay2.js +541 -0
  48. package/dist/envelope/replay.d.ts +45 -0
  49. package/dist/envelope/replay.js +186 -0
  50. package/dist/envelope/stream.d.ts +78 -0
  51. package/dist/envelope/stream.js +372 -0
  52. package/dist/errors.d.ts +21 -0
  53. package/dist/errors.js +300 -0
  54. package/dist/index.d.ts +25 -0
  55. package/dist/index.js +23 -0
  56. package/dist/keys/near-ckd.d.ts +47 -0
  57. package/dist/keys/near-ckd.js +96 -0
  58. package/dist/limits.d.ts +4 -0
  59. package/dist/limits.js +4 -0
  60. package/dist/near/nep413.d.ts +22 -0
  61. package/dist/near/nep413.js +39 -0
  62. package/dist/near/rpc.d.ts +170 -0
  63. package/dist/near/rpc.js +423 -0
  64. package/dist/near/texts.d.ts +39 -0
  65. package/dist/near/texts.js +60 -0
  66. package/dist/net/ip.d.ts +7 -0
  67. package/dist/net/ip.js +62 -0
  68. package/dist/net/retry.d.ts +3 -0
  69. package/dist/net/retry.js +31 -0
  70. package/dist/node/adapter-checks.d.ts +6 -0
  71. package/dist/node/adapter-checks.js +13 -0
  72. package/dist/node/adapter.d.ts +8 -0
  73. package/dist/node/adapter.js +98 -0
  74. package/dist/node/agent.d.ts +49 -0
  75. package/dist/node/agent.js +266 -0
  76. package/dist/node/amounts.d.ts +2 -0
  77. package/dist/node/amounts.js +20 -0
  78. package/dist/node/browser-login.d.ts +25 -0
  79. package/dist/node/browser-login.js +219 -0
  80. package/dist/node/budget.d.ts +24 -0
  81. package/dist/node/budget.js +59 -0
  82. package/dist/node/buy-commands.d.ts +24 -0
  83. package/dist/node/buy-commands.js +301 -0
  84. package/dist/node/cli.d.ts +60 -0
  85. package/dist/node/cli.js +201 -0
  86. package/dist/node/command-context.d.ts +82 -0
  87. package/dist/node/command-context.js +77 -0
  88. package/dist/node/config.d.ts +37 -0
  89. package/dist/node/config.js +189 -0
  90. package/dist/node/core-adapter.d.ts +43 -0
  91. package/dist/node/core-adapter.js +122 -0
  92. package/dist/node/errors.d.ts +8 -0
  93. package/dist/node/errors.js +12 -0
  94. package/dist/node/index.d.ts +7 -0
  95. package/dist/node/index.js +5 -0
  96. package/dist/node/io.d.ts +13 -0
  97. package/dist/node/io.js +112 -0
  98. package/dist/node/keychain.d.ts +10 -0
  99. package/dist/node/keychain.js +67 -0
  100. package/dist/node/main.d.ts +2 -0
  101. package/dist/node/main.js +21 -0
  102. package/dist/node/offers.d.ts +16 -0
  103. package/dist/node/offers.js +91 -0
  104. package/dist/node/origin.d.ts +11 -0
  105. package/dist/node/origin.js +80 -0
  106. package/dist/node/paths.d.ts +3 -0
  107. package/dist/node/paths.js +71 -0
  108. package/dist/node/payment-terms.d.ts +26 -0
  109. package/dist/node/payment-terms.js +127 -0
  110. package/dist/node/purchase-commands.d.ts +16 -0
  111. package/dist/node/purchase-commands.js +237 -0
  112. package/dist/node/purchase-guard.d.ts +19 -0
  113. package/dist/node/purchase-guard.js +53 -0
  114. package/dist/node/relay-transport.d.ts +6 -0
  115. package/dist/node/relay-transport.js +173 -0
  116. package/dist/node/resources.d.ts +2 -0
  117. package/dist/node/resources.js +26 -0
  118. package/dist/node/retry-gate.d.ts +15 -0
  119. package/dist/node/retry-gate.js +53 -0
  120. package/dist/node/seller-commands.d.ts +12 -0
  121. package/dist/node/seller-commands.js +207 -0
  122. package/dist/node/sharing.d.ts +3 -0
  123. package/dist/node/sharing.js +28 -0
  124. package/dist/node/shops.d.ts +17 -0
  125. package/dist/node/shops.js +74 -0
  126. package/dist/node/signer-mock.d.ts +11 -0
  127. package/dist/node/signer-mock.js +79 -0
  128. package/dist/node/signer-wallet.d.ts +8 -0
  129. package/dist/node/signer-wallet.js +149 -0
  130. package/dist/node/signing.d.ts +29 -0
  131. package/dist/node/signing.js +200 -0
  132. package/dist/node/storage-commands.d.ts +11 -0
  133. package/dist/node/storage-commands.js +50 -0
  134. package/dist/node/sync-dir.d.ts +1 -0
  135. package/dist/node/sync-dir.js +11 -0
  136. package/dist/node/wallets.d.ts +13 -0
  137. package/dist/node/wallets.js +146 -0
  138. package/dist/oneclick/oneclick.d.ts +132 -0
  139. package/dist/oneclick/oneclick.js +342 -0
  140. package/dist/pay/backup.d.ts +70 -0
  141. package/dist/pay/backup.js +402 -0
  142. package/dist/pay/base.d.ts +135 -0
  143. package/dist/pay/base.js +386 -0
  144. package/dist/pay/eip3009.d.ts +59 -0
  145. package/dist/pay/eip3009.js +72 -0
  146. package/dist/pay/pay.d.ts +86 -0
  147. package/dist/pay/pay.js +297 -0
  148. package/dist/pay/purchase.d.ts +103 -0
  149. package/dist/pay/purchase.js +20 -0
  150. package/dist/pay/recover.d.ts +31 -0
  151. package/dist/pay/recover.js +34 -0
  152. package/dist/pay/seller.d.ts +130 -0
  153. package/dist/pay/seller.js +444 -0
  154. package/dist/pay/settle.d.ts +96 -0
  155. package/dist/pay/settle.js +308 -0
  156. package/dist/pay/split.d.ts +115 -0
  157. package/dist/pay/split.js +256 -0
  158. package/dist/pay/store-node.d.ts +8 -0
  159. package/dist/pay/store-node.js +224 -0
  160. package/dist/pay/store.d.ts +54 -0
  161. package/dist/pay/store.js +135 -0
  162. package/dist/pay/x402.d.ts +95 -0
  163. package/dist/pay/x402.js +136 -0
  164. package/dist/relay/admission.d.ts +8 -0
  165. package/dist/relay/admission.js +58 -0
  166. package/dist/relay/capabilities.d.ts +36 -0
  167. package/dist/relay/capabilities.js +232 -0
  168. package/dist/relay/fees.d.ts +17 -0
  169. package/dist/relay/fees.js +105 -0
  170. package/dist/relay/index.d.ts +10 -0
  171. package/dist/relay/index.js +8 -0
  172. package/dist/relay/keeper-balance.d.ts +17 -0
  173. package/dist/relay/keeper-balance.js +46 -0
  174. package/dist/relay/keeper-runner.d.ts +114 -0
  175. package/dist/relay/keeper-runner.js +703 -0
  176. package/dist/relay/keeper.d.ts +38 -0
  177. package/dist/relay/keeper.js +73 -0
  178. package/dist/relay/ledger.d.ts +155 -0
  179. package/dist/relay/ledger.js +392 -0
  180. package/dist/relay/relay-checks.d.ts +3 -0
  181. package/dist/relay/relay-checks.js +244 -0
  182. package/dist/relay/relay-reconciliation.d.ts +15 -0
  183. package/dist/relay/relay-reconciliation.js +293 -0
  184. package/dist/relay/relay-request.d.ts +6 -0
  185. package/dist/relay/relay-request.js +139 -0
  186. package/dist/relay/relay-transactions.d.ts +23 -0
  187. package/dist/relay/relay-transactions.js +182 -0
  188. package/dist/relay/relay-types.d.ts +128 -0
  189. package/dist/relay/relay-types.js +17 -0
  190. package/dist/relay/relay.d.ts +102 -0
  191. package/dist/relay/relay.js +426 -0
  192. package/dist/relay/reservation.d.ts +29 -0
  193. package/dist/relay/reservation.js +132 -0
  194. package/dist/relay/sponsorship.d.ts +42 -0
  195. package/dist/relay/sponsorship.js +184 -0
  196. package/dist/routes.d.ts +2 -0
  197. package/dist/routes.js +1 -0
  198. package/dist/settle-near/codec.d.ts +17 -0
  199. package/dist/settle-near/codec.js +86 -0
  200. package/dist/settle-near/identity.d.ts +27 -0
  201. package/dist/settle-near/identity.js +80 -0
  202. package/dist/settle-near/purchase.d.ts +40 -0
  203. package/dist/settle-near/purchase.js +153 -0
  204. package/dist/settle-near/terms.d.ts +37 -0
  205. package/dist/settle-near/terms.js +89 -0
  206. package/dist/shops/discovery.d.ts +95 -0
  207. package/dist/shops/discovery.js +384 -0
  208. package/dist/wallet/account-only.d.ts +11 -0
  209. package/dist/wallet/account-only.js +6 -0
  210. package/dist/wallet/uncertain.d.ts +8 -0
  211. package/dist/wallet/uncertain.js +13 -0
  212. package/dist/wallet/wallet.d.ts +100 -0
  213. package/dist/wallet/wallet.js +204 -0
  214. package/package.json +136 -3
@@ -0,0 +1,286 @@
1
+ /** Page-owned providers adapted to Annon wallets. No wallet packages or browser globals. */
2
+ import { base58, base64 } from '@scure/base';
3
+ import { parseUploadIntent, uploadText, } from '../download/upload.js';
4
+ import { AnnonError, present } from '../errors.js';
5
+ import { proveNearControl, verifyNearMessage, } from '../near/nep413.js';
6
+ import { BASE_CHAIN_ID, digest, signer } from '../pay/eip3009.js';
7
+ import { bytes, hex } from '../settle-near/codec.js';
8
+ import { parseIdentity, verifyAuthorization } from '../settle-near/identity.js';
9
+ import { TransactionUncertain } from '../wallet/uncertain.js';
10
+ import { evmWallet, nearSelectorWallet, } from '../wallet/wallet.js';
11
+ export class BrowserWalletError extends AnnonError {
12
+ code;
13
+ constructor(code, message, options) {
14
+ super(code, message, options);
15
+ this.code = code;
16
+ this.name = 'BrowserWalletError';
17
+ }
18
+ }
19
+ function fail(code, message) {
20
+ throw new BrowserWalletError(code, message);
21
+ }
22
+ /** Wallets differ in rejection shape; unwrap transport errors without exposing their text to a page. */
23
+ async function checked(run) {
24
+ try {
25
+ return await run();
26
+ }
27
+ catch (error) {
28
+ if (error instanceof BrowserWalletError || error instanceof TransactionUncertain)
29
+ throw error;
30
+ let cause = error;
31
+ for (let depth = 0; depth < 8 && cause && typeof cause === 'object'; depth++) {
32
+ const e = cause;
33
+ if (e.code === 4001 || e.code === 'ACTION_REJECTED')
34
+ throw new BrowserWalletError('rejected', 'The wallet request was rejected.', {
35
+ cause: error,
36
+ });
37
+ if (e.code === 4901 || e.code === 4902)
38
+ throw new BrowserWalletError('wrong_chain', 'Select Base in the wallet.', { cause: error });
39
+ if (e.code === -32601 || e.code === 4200)
40
+ throw new BrowserWalletError('missing_method', 'The wallet does not support this method.', {
41
+ cause: error,
42
+ });
43
+ cause = e.cause;
44
+ }
45
+ throw new BrowserWalletError('wallet_error', 'The wallet request failed.', { cause: error });
46
+ }
47
+ }
48
+ /** Checks Base before signing and after the result. Switching always asks the page's provider. */
49
+ export function browserEvmWallet(provider, address) {
50
+ const identity = parseIdentity({ kind: 'evm', id: address });
51
+ const request = (q) => checked(async () => {
52
+ if (typeof provider.request !== 'function')
53
+ fail('missing_method', 'EIP-1193 request is unavailable.');
54
+ const result = await provider.request(q);
55
+ if (q.method === 'eth_accounts' &&
56
+ (!Array.isArray(result) ||
57
+ !result.some((a) => typeof a === 'string' && a.toLowerCase() === identity.id)))
58
+ fail('wrong_identity', 'The wallet does not control the selected identity.');
59
+ return result;
60
+ });
61
+ const underlying = evmWallet({ request }, identity.id);
62
+ const chain = async () => {
63
+ const id = await request({ method: 'eth_chainId' });
64
+ try {
65
+ if (typeof id !== 'string' || !/^0x[0-9a-f]+$/i.test(id))
66
+ return false;
67
+ return BigInt(id) === BigInt(BASE_CHAIN_ID);
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ };
73
+ const selected = async (switchChain) => {
74
+ if (!(await chain())) {
75
+ if (switchChain)
76
+ await request({ method: 'wallet_switchEthereumChain', params: [{ chainId: '0x2105' }] });
77
+ if (!switchChain || !(await chain()))
78
+ fail('wrong_chain', 'Select Base in the wallet.');
79
+ }
80
+ await request({ method: 'eth_accounts' });
81
+ };
82
+ return {
83
+ identity,
84
+ address: identity.id,
85
+ authorize: (text) => checked(async () => {
86
+ // personal_sign does not depend on the chain: recovery works on any network the wallet is on.
87
+ await request({ method: 'eth_accounts' });
88
+ // Share the EIP-191 signing path used by browser login.
89
+ let auth;
90
+ try {
91
+ auth = await underlying.authorize(text);
92
+ }
93
+ catch (error) {
94
+ if (error instanceof AnnonError && error.code === 'invalid_signature')
95
+ fail('invalid_signature', 'The wallet returned an invalid recovery signature.');
96
+ throw error;
97
+ }
98
+ if (!verifyAuthorization(identity, text, auth))
99
+ fail('invalid_signature', 'The wallet returned an invalid recovery signature.');
100
+ await request({ method: 'eth_accounts' });
101
+ return auth;
102
+ }),
103
+ signTypedData: (data) => checked(async () => {
104
+ if (data.domain.chainId !== BASE_CHAIN_ID)
105
+ fail('wrong_chain', 'Payment authorization must name Base.');
106
+ if (data.message.from.toLowerCase() !== identity.id)
107
+ fail('wrong_identity', 'Payment authorization names another identity.');
108
+ await selected(true);
109
+ const sig = await underlying.signTypedData(data);
110
+ if (typeof sig !== 'string' ||
111
+ signer(digest(data.domain.verifyingContract, data.message), sig) !== identity.id)
112
+ fail('invalid_signature', 'The wallet returned an invalid payment signature.');
113
+ await selected(false);
114
+ return sig;
115
+ }),
116
+ };
117
+ }
118
+ function solanaId(key) {
119
+ try {
120
+ if (!key)
121
+ return fail('wrong_identity', 'No Solana identity is selected.');
122
+ return parseIdentity({
123
+ kind: 'solana',
124
+ id: typeof key === 'string'
125
+ ? key
126
+ : base58.encode(key instanceof Uint8Array ? key : key.toBytes()),
127
+ }).id;
128
+ }
129
+ catch {
130
+ return fail('wrong_identity', 'The wallet returned another Solana identity.');
131
+ }
132
+ }
133
+ export function browserSolanaWallet(provider, address) {
134
+ const identity = parseIdentity({ kind: 'solana', id: address });
135
+ const selected = () => {
136
+ if (solanaId(provider.publicKey) !== identity.id)
137
+ fail('wrong_identity', 'Select the requested Solana identity.');
138
+ };
139
+ return {
140
+ identity,
141
+ authorize: (text) => checked(async () => {
142
+ selected();
143
+ const signMessage = provider.signMessage?.bind(provider);
144
+ if (typeof signMessage !== 'function')
145
+ fail('missing_method', 'Solana signMessage is unavailable.');
146
+ const result = await signMessage(new TextEncoder().encode(text));
147
+ const signature = result instanceof Uint8Array ? result : result?.signature;
148
+ if (!(result instanceof Uint8Array) &&
149
+ result?.publicKey &&
150
+ solanaId(result.publicKey) !== identity.id)
151
+ fail('wrong_identity', 'The signature names another Solana identity.');
152
+ if (!(signature instanceof Uint8Array) || signature.length !== 64)
153
+ fail('invalid_signature', 'The wallet returned an invalid Solana signature.');
154
+ const auth = { kind: 'solana', sig: hex(signature) };
155
+ if (!verifyAuthorization(identity, text, auth))
156
+ fail('invalid_signature', 'The wallet did not sign the exact recovery text.');
157
+ selected();
158
+ return auth;
159
+ }),
160
+ };
161
+ }
162
+ export function browserNearWallet(provider, accountId) {
163
+ const identity = parseIdentity({ kind: 'near', id: accountId });
164
+ const selected = async () => {
165
+ if (typeof provider.getAccounts !== 'function')
166
+ fail('missing_method', 'NEAR getAccounts is unavailable.');
167
+ const accounts = await provider.getAccounts();
168
+ if (!Array.isArray(accounts) || !accounts.some((a) => a?.accountId === identity.id))
169
+ fail('wrong_identity', 'Select the requested NEAR identity.');
170
+ return accounts;
171
+ };
172
+ const underlying = nearSelectorWallet({
173
+ getAccounts: selected,
174
+ signAndSendTransaction: async (tx) => {
175
+ if (typeof provider.signAndSendTransaction !== 'function')
176
+ fail('missing_method', 'NEAR transaction signing is unavailable.');
177
+ const result = await provider.signAndSendTransaction({
178
+ signerId: tx.signerId,
179
+ receiverId: tx.receiverId,
180
+ actions: tx.actions.map(({ params }) => ({
181
+ functionCall: {
182
+ methodName: params.methodName,
183
+ args: new TextEncoder().encode(JSON.stringify(params.args)),
184
+ gas: BigInt(params.gas),
185
+ deposit: BigInt(params.deposit),
186
+ },
187
+ })),
188
+ });
189
+ if (result && typeof result === 'object' && 'transaction' in result) {
190
+ const transaction = result.transaction;
191
+ if (transaction?.signer_id !== identity.id) {
192
+ if (transaction?.hash)
193
+ throw new TransactionUncertain(transaction.hash);
194
+ fail('wrong_identity', 'The transaction names another NEAR identity.');
195
+ }
196
+ }
197
+ else
198
+ fail('invalid_response', 'The wallet returned no NEAR transaction.');
199
+ return result;
200
+ },
201
+ }, identity.id);
202
+ return {
203
+ identity,
204
+ authorize: (text) => checked(() => underlying.authorize(text)),
205
+ call: (call) => checked(async () => {
206
+ const value = await underlying.call(call);
207
+ try {
208
+ await selected();
209
+ }
210
+ catch {
211
+ const tx = value.transaction;
212
+ throw new TransactionUncertain(tx.hash);
213
+ }
214
+ return value;
215
+ }),
216
+ transferPurchase: (message, assets) => checked(() => underlying.transferPurchase(message, assets)),
217
+ proveControl: (text, context) => checked(async () => {
218
+ await selected();
219
+ const signMessage = provider.signMessage?.bind(provider);
220
+ if (typeof signMessage !== 'function')
221
+ fail('missing_method', 'NEAR recovery requires NEP-413 signMessage.');
222
+ try {
223
+ await proveNearControl(identity.id, text, context, async (p) => {
224
+ const result = await signMessage(p);
225
+ if (!result)
226
+ fail('invalid_response', 'The wallet returned no NEP-413 signature.');
227
+ if (result.accountId !== identity.id)
228
+ fail('wrong_identity', 'The signature names another NEAR identity.');
229
+ try {
230
+ if (typeof result.publicKey !== 'string' ||
231
+ !result.publicKey.startsWith('ed25519:') ||
232
+ base58.decode(result.publicKey.slice(8)).length !== 32 ||
233
+ typeof result.signature !== 'string' ||
234
+ base64.decode(result.signature).length !== 64)
235
+ fail('invalid_signature', 'The wallet returned a malformed NEP-413 signature.');
236
+ }
237
+ catch {
238
+ fail('invalid_signature', 'The wallet returned a malformed NEP-413 signature.');
239
+ }
240
+ return result;
241
+ });
242
+ }
243
+ catch (error) {
244
+ if (error instanceof BrowserWalletError)
245
+ throw error;
246
+ if (error instanceof AnnonError && error.code === 'invalid_signature')
247
+ fail('invalid_signature', 'The wallet returned an invalid NEP-413 ownership proof.');
248
+ throw error;
249
+ }
250
+ await selected();
251
+ }),
252
+ };
253
+ }
254
+ /** Sign only the hosting payload; no callback URL or page state is authorized. */
255
+ export async function signNearUpload(provider, input, nearRpc) {
256
+ const intent = parseUploadIntent(input);
257
+ if (intent.seller.kind !== 'near')
258
+ throw new AnnonError('wrong_identity');
259
+ return checked(async () => {
260
+ const selected = async () => {
261
+ if (!provider.getAccounts || !provider.signMessage)
262
+ fail('missing_method', 'NEAR hosting requires NEP-413 signing.');
263
+ const accounts = await provider.getAccounts();
264
+ if (!accounts.some((a) => a.accountId === intent.seller.id))
265
+ fail('wrong_identity', 'Select the requested NEAR identity.');
266
+ };
267
+ await selected();
268
+ const payload = {
269
+ message: uploadText(intent),
270
+ recipient: intent.hostOrigin,
271
+ nonce: bytes(intent.nonce, 32),
272
+ };
273
+ const result = await present(provider.signMessage, 'invalid_response').call(provider, {
274
+ ...payload,
275
+ nonce: payload.nonce.slice(),
276
+ });
277
+ await verifyNearMessage(intent.seller.id, payload, result, nearRpc);
278
+ await selected();
279
+ return {
280
+ kind: 'near',
281
+ accountId: present(result, 'invalid_response').accountId,
282
+ publicKey: present(result, 'invalid_response').publicKey,
283
+ signature: present(result, 'invalid_response').signature,
284
+ };
285
+ });
286
+ }
@@ -0,0 +1,4 @@
1
+ /** Byte operations shared without changing view, iterator or allocation semantics. */
2
+ export declare function concatParts(parts: readonly Uint8Array[]): Uint8Array<ArrayBuffer>;
3
+ export declare function hexDigits(b: Uint8Array): string;
4
+ export declare function prefixedHex(b: Uint8Array): string;
package/dist/bytes.js ADDED
@@ -0,0 +1,16 @@
1
+ /** Byte operations shared without changing view, iterator or allocation semantics. */
2
+ export function concatParts(parts) {
3
+ const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));
4
+ let at = 0;
5
+ for (const p of parts) {
6
+ out.set(p, at);
7
+ at += p.length;
8
+ }
9
+ return out;
10
+ }
11
+ export function hexDigits(b) {
12
+ return Array.from(b, (x) => x.toString(16).padStart(2, '0')).join('');
13
+ }
14
+ export function prefixedHex(b) {
15
+ return `0x${hexDigits(b)}`;
16
+ }
@@ -0,0 +1,59 @@
1
+ import { AnnonError } from '../errors.js';
2
+ export type DownloadErrorCode =
3
+ /** The host answered something this protocol does not allow. */
4
+ 'bad_response'
5
+ /** The host did not accept the payment or purchase grant proof. */
6
+ | 'not_authorized'
7
+ /** The payment is still settling after every retry; send the same payload again later. */
8
+ | 'settlement_pending'
9
+ /** The bytes are not the file whose header was checked before paying. */
10
+ | 'file_mismatch'
11
+ /** The caller cancelled the download. */
12
+ | 'cancelled'
13
+ /** Encrypted downloads enforce the shared PAY2 size limit. */
14
+ | 'too_large' | 'download_limited' | 'download_in_progress' | 'rate_limited' | 'unavailable' | 'not_sponsored' | 'relayer_unavailable';
15
+ export declare class DownloadError extends AnnonError {
16
+ readonly code: DownloadErrorCode;
17
+ retryAfterSeconds?: number;
18
+ purchaseId?: string;
19
+ fileId?: string;
20
+ constructor(code: DownloadErrorCode, message?: string);
21
+ }
22
+ /**
23
+ * Gated downloads go over HTTPS only: on plain HTTP anyone on the path reads the body or races the
24
+ * buyer with the intercepted authorization. Plain HTTP only for this machine, in development.
25
+ */
26
+ export declare function secureUrl(url: string): URL;
27
+ export interface DownloadOptions {
28
+ /** The file: the offer's `resource.url`. */
29
+ url: string;
30
+ contractId: string;
31
+ fileId: string;
32
+ /** The header the buyer checked before paying (`Quote.header`). */
33
+ header: Uint8Array;
34
+ /** A grant key, obtained from this purchase or wallet recovery. */
35
+ proof: {
36
+ secret: Uint8Array;
37
+ purchase_id: string;
38
+ grant: number;
39
+ };
40
+ payment?: {
41
+ header: string;
42
+ };
43
+ /** Attempts after a broken connection; each resumes from the last checked chunk. */
44
+ retries?: number;
45
+ /** How often a payment that is still settling is asked again (default 40). */
46
+ settleTries?: number;
47
+ /** Waits between those (default: `Retry-After`, or 3 s). */
48
+ wait?: (ms: number) => Promise<void>;
49
+ fetch?: typeof fetch;
50
+ /** Unix seconds; defaults to now. */
51
+ now?: () => number;
52
+ maxBytes?: number;
53
+ signal?: AbortSignal;
54
+ }
55
+ /**
56
+ * The file as a stream: the header first, then each chunk once its hash matches. Throws
57
+ * `DownloadError`; a broken connection is retried from the last checked chunk.
58
+ */
59
+ export declare function download(o: DownloadOptions): ReadableStream<Uint8Array>;