@phala/pay 0.11.4 → 0.12.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/README.md +48 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/wallet.d.ts +25 -0
- package/dist/wallet.d.ts.map +1 -1
- package/dist/wallet.js +31 -10
- package/dist/wallet.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/wallet.ts +65 -10
package/README.md
CHANGED
|
@@ -204,6 +204,36 @@ import { PaymentElement } from "@phala/pay-react";
|
|
|
204
204
|
exchange? Use a deposit address", for payers sending from an exchange or any wallet: it resolves
|
|
205
205
|
with the deposit address's `address` and `networks` and, to follow its payments, `clientSecret`;
|
|
206
206
|
the element shows `<DepositAddress>` at the chosen option, which states the per-transfer limits.
|
|
207
|
+
- **Deposit-address mode.** Without `createQuote`, submit calls `createDepositAddress(option)` once
|
|
208
|
+
and shows that address as the way to pay, with no secondary line: the customer's one fixed address
|
|
209
|
+
instead of a new quote per payment. `depositAmountAtomic(option, token)` names the token amount to
|
|
210
|
+
ask for in the token's smallest unit (`undefined` for any amount); it is called once the address
|
|
211
|
+
is created, with its token for the chosen option, whose `decimals` give the unit. The address view
|
|
212
|
+
then states the amount and network once, pays it with `Pay with <wallet name>`
|
|
213
|
+
(`payDepositAddressWithWallet`: exactly that amount, then a transaction-hash hint), and keeps a QR
|
|
214
|
+
code that requests the amount (EIP-681 `uint256`) and the address to copy behind "Pay from an
|
|
215
|
+
exchange or another wallet". It follows the payment the wallet sent, by its hash, or else the
|
|
216
|
+
newest one that arrives after the address was first read, on one status line; `onChange` reports
|
|
217
|
+
it as `payment`, and `onDepositSuccess(payment)` is called once when it is credited. An address
|
|
218
|
+
that does not take the chosen token on the chosen network is a `createDepositAddress` failure. To
|
|
219
|
+
resume after a reload, keep `onDepositSent(txHash, chainId)`'s values and pass them back as
|
|
220
|
+
`depositTxHash`, with that option as `value` or `defaultValue`: the element calls
|
|
221
|
+
`createDepositAddress` at once and shows that payment's status (no way to pay again) until it is
|
|
222
|
+
credited.
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
<PaymentElement
|
|
226
|
+
options={paymentOptions(config.assets)}
|
|
227
|
+
amount={2500}
|
|
228
|
+
// POST /v1/deposit_addresses on your backend: { address, networks, clientSecret }
|
|
229
|
+
createDepositAddress={() => api.depositAddress()}
|
|
230
|
+
// 25 of a $1 stablecoin: cents × 10^(decimals − 2)
|
|
231
|
+
depositAmountAtomic={(option, token) => (2500n * 10n ** BigInt(token.decimals)) / 100n}
|
|
232
|
+
apiBase="https://pay.example.com"
|
|
233
|
+
onDepositSuccess={() => router.refresh()}
|
|
234
|
+
/>
|
|
235
|
+
```
|
|
236
|
+
|
|
207
237
|
- Your own content: `children` go inside the form, under the token and network and above the
|
|
208
238
|
element's button, while the payer chooses. With `hideSubmit`, put your summary and your
|
|
209
239
|
`type="submit"` button there, and the deposit-address line follows your button:
|
|
@@ -219,8 +249,9 @@ import { PaymentElement } from "@phala/pay-react";
|
|
|
219
249
|
button `type="submit" form={id}` (or call `requestSubmit()` on the form with that id). The
|
|
220
250
|
element is a `<form>`: do not nest it in another one.
|
|
221
251
|
- `value` and `onOptionChange` control the choice (`defaultValue` sets the first one otherwise);
|
|
222
|
-
`onChange({ step, checkout })` reports each step (`options`, `creating`, `checkout`,
|
|
223
|
-
`deposit_address`) and, while paying, each checkout status change
|
|
252
|
+
`onChange({ step, checkout, payment })` reports each step (`options`, `creating`, `checkout`,
|
|
253
|
+
`deposit_address`) and, while paying, each checkout status change or, with
|
|
254
|
+
`depositAmountAtomic`, each change of the deposit address's payment; `onSuccess`, `onExpire`,
|
|
224
255
|
`onWalletError`, `walletClient`, `pollInterval`, and `appearance` are `<Checkout>`'s.
|
|
225
256
|
|
|
226
257
|
### Payment options
|
|
@@ -299,8 +330,22 @@ not report loading. Unchanged polls, callback replacements,
|
|
|
299
330
|
and reconnecting alone do not trigger it. Use it to update your page without additional polling;
|
|
300
331
|
fulfil from the `deposit.credited` webhook.
|
|
301
332
|
|
|
333
|
+
With `amountAtomic` (an amount of the token at `chainId` and `asset`, which then stay fixed), it
|
|
334
|
+
asks for that amount instead: the amount and network stated once, a `Pay with <wallet name>` button
|
|
335
|
+
(`walletClient`, `buttonText`, and `onWalletError` as `<Checkout>`'s), and "Pay from an exchange or
|
|
336
|
+
another wallet" revealing a QR code that requests exactly the amount and the address to copy (shown
|
|
337
|
+
at once when the browser has no wallet). With `clientSecret` and `apiBase` it follows that payment
|
|
338
|
+
(the wallet's transaction by its hash, else the newest payment that arrives after the address was
|
|
339
|
+
first read) on one status line, calls `onPaymentChange(payment)` as it changes and `onSuccess(payment)`
|
|
340
|
+
once it is credited, and replaces the ways to pay with that status once it is on its way.
|
|
341
|
+
`onSent(txHash, chainId)` reports the wallet's transaction; pass it back as `txHash` after a
|
|
342
|
+
reload to follow that payment again.
|
|
343
|
+
|
|
302
344
|
`depositAddressTransfer(network, asset)` reads and checks one token's amount-less EIP-681
|
|
303
|
-
`payment_uri` without React
|
|
345
|
+
`payment_uri` without React; `payDepositAddressWithWallet(wallet, { network, asset, amountAtomic,
|
|
346
|
+
clientSecret?, apiBase? })` pays an amount of it from a wallet as `payWithWallet` pays a quote
|
|
347
|
+
(connect, switch chain, balance check, `transfer`), then, with `clientSecret` and `apiBase`, hints
|
|
348
|
+
the transaction with its `chain_id` without waiting on the hint, and resolves with the hash.
|
|
304
349
|
|
|
305
350
|
## Appearance
|
|
306
351
|
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { depositAddressTransfer, parseTransferUri, quoteTransfer, type DepositAd
|
|
|
7
7
|
export { parseClientQuote, quoteIdFromClientSecret, type ClientQuote } from "./quote.js";
|
|
8
8
|
export { assetIconName, assetName, assetSymbol, iconMonogram, type IconName } from "./icon-names.js";
|
|
9
9
|
export { paymentOptionLabel, paymentOptions, samePaymentOption, type NetworkPaymentOption, type PaymentNetwork, type PaymentOption, } from "./options.js";
|
|
10
|
-
export { INJECTED_WALLET_UUID, WalletError, payWithWallet, watchWallets, type EthereumProvider, type Wallet, type WalletErrorCode, type WalletInfo, } from "./wallet.js";
|
|
10
|
+
export { INJECTED_WALLET_UUID, WalletError, payDepositAddressWithWallet, payWithWallet, watchWallets, type EthereumProvider, type PayDepositAddressOptions, type Wallet, type WalletErrorCode, type WalletInfo, } from "./wallet.js";
|
|
11
11
|
export { networkIcon, assetIcon } from "./icons.js";
|
|
12
12
|
export type { CheckoutParams } from "./shared/checkout-params.js";
|
|
13
13
|
export { submitTransaction, type SubmitTransactionOptions } from "./transactions.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,GACnC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/I,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrG,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,GACnC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/I,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrG,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,2BAA2B,EAC3B,aAAa,EACb,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export { depositAddressTransfer, parseTransferUri, quoteTransfer, } from "./paym
|
|
|
7
7
|
export { parseClientQuote, quoteIdFromClientSecret } from "./quote.js";
|
|
8
8
|
export { assetIconName, assetName, assetSymbol, iconMonogram } from "./icon-names.js";
|
|
9
9
|
export { paymentOptionLabel, paymentOptions, samePaymentOption, } from "./options.js";
|
|
10
|
-
export { INJECTED_WALLET_UUID, WalletError, payWithWallet, watchWallets, } from "./wallet.js";
|
|
10
|
+
export { INJECTED_WALLET_UUID, WalletError, payDepositAddressWithWallet, payWithWallet, watchWallets, } from "./wallet.js";
|
|
11
11
|
export { networkIcon, assetIcon } from "./icons.js";
|
|
12
12
|
export { submitTransaction } from "./transactions.js";
|
|
13
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,GAQd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAwB,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,sBAAsB,GAKvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/I,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GAMd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAoB,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAiB,MAAM,iBAAiB,CAAC;AACrG,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,GAIlB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,GAQd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAwB,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,sBAAsB,GAKvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/I,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GAMd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAoB,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAiB,MAAM,iBAAiB,CAAC;AACrG,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,GAIlB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,2BAA2B,EAC3B,aAAa,EACb,YAAY,GAMb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EAAE,iBAAiB,EAAiC,MAAM,mBAAmB,CAAC"}
|
package/dist/wallet.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Hash, type WalletClient } from "viem";
|
|
2
|
+
import { type DepositAddressAsset, type DepositAddressNetwork } from "./payment.js";
|
|
2
3
|
import type { ClientQuote } from "./quote.js";
|
|
3
4
|
/** EIP-6963 provider info. */
|
|
4
5
|
export interface WalletInfo {
|
|
@@ -43,4 +44,28 @@ export declare class WalletError extends Error {
|
|
|
43
44
|
* it; the checkout's status follows the payment from there.
|
|
44
45
|
*/
|
|
45
46
|
export declare function payWithWallet(wallet: WalletClient | EthereumProvider, quote: ClientQuote): Promise<Hash>;
|
|
47
|
+
export interface PayDepositAddressOptions {
|
|
48
|
+
/** The network to pay on, from the deposit address's `networks`. */
|
|
49
|
+
network: DepositAddressNetwork;
|
|
50
|
+
/** The token to pay in, from that network's `assets`. */
|
|
51
|
+
asset: DepositAddressAsset;
|
|
52
|
+
/** The token amount to send, in the smallest unit; positive. */
|
|
53
|
+
amountAtomic: bigint;
|
|
54
|
+
/**
|
|
55
|
+
* The address's `client_secret`. With `apiBase`, the transaction hash is sent to the service as
|
|
56
|
+
* a best-effort hint once the wallet broadcasts it, so the payment is found within about a block.
|
|
57
|
+
*/
|
|
58
|
+
clientSecret?: string | undefined;
|
|
59
|
+
/** The service origin; needed with `clientSecret`. */
|
|
60
|
+
apiBase?: string | undefined;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Pays `amountAtomic` of a token to a customer's deposit address from a wallet, as `payWithWallet`
|
|
64
|
+
* pays a quote: connects, switches to (or adds) the network's chain, checks the token balance, and
|
|
65
|
+
* sends the ERC-20 `transfer` that the token's `payment_uri` states, for exactly that amount. Then,
|
|
66
|
+
* with `clientSecret` and `apiBase`, it hints the transaction to the service without waiting for
|
|
67
|
+
* or failing on it. Resolves with the transaction hash once the wallet has broadcast it; follow the
|
|
68
|
+
* payment in the address's `payments` by that hash.
|
|
69
|
+
*/
|
|
70
|
+
export declare function payDepositAddressWithWallet(wallet: WalletClient | EthereumProvider, { network, asset, amountAtomic, clientSecret, apiBase }: PayDepositAddressOptions): Promise<Hash>;
|
|
46
71
|
//# sourceMappingURL=wallet.d.ts.map
|
package/dist/wallet.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAEA,OAAO,EAQL,KAAK,IAAI,EACT,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAEA,OAAO,EAQL,KAAK,IAAI,EACT,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;AAId,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAE3B,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,8BAA8B;AAC9B,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,2FAA2F;AAC3F,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,iGAAiG;AACjG,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAa9E;AA8BD,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,YAAY,GACZ,aAAa,GACb,sBAAsB,GACtB,QAAQ,CAAC;AAEb,qBAAa,WAAY,SAAQ,KAAK;IAIlC,QAAQ,CAAC,IAAI,EAAE,eAAe;IAHhC,SAAkB,IAAI,iBAAiB;gBAG5B,IAAI,EAAE,eAAe,EAC9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY;CAIzB;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,GAAG,gBAAgB,EACvC,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,OAAO,EAAE,qBAAqB,CAAC;IAC/B,yDAAyD;IACzD,KAAK,EAAE,mBAAmB,CAAC;IAC3B,gEAAgE;IAChE,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,YAAY,GAAG,gBAAgB,EACvC,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,wBAAwB,GAChF,OAAO,CAAC,IAAI,CAAC,CAYf"}
|
package/dist/wallet.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { submitWalletTransaction } from "./transactions.js";
|
|
1
|
+
import { submitTransaction, submitWalletTransaction } from "./transactions.js";
|
|
2
2
|
import { createStore } from "mipd";
|
|
3
3
|
import { BaseError, createWalletClient, custom, erc20Abi, SwitchChainError, UserRejectedRequestError, } from "viem";
|
|
4
4
|
import { readContract } from "viem/actions";
|
|
5
5
|
import { knownChain, networkName } from "./chains.js";
|
|
6
|
-
import {
|
|
7
|
-
import { quoteTransfer } from "./payment.js";
|
|
6
|
+
import { formatUnitsGrouped } from "./format.js";
|
|
7
|
+
import { depositAddressTransfer, quoteTransfer, } from "./payment.js";
|
|
8
8
|
/** The legacy `window.ethereum` provider, offered when no wallet announces itself (EIP-6963). */
|
|
9
9
|
export const INJECTED_WALLET_UUID = "injected";
|
|
10
10
|
/**
|
|
@@ -68,7 +68,30 @@ export class WalletError extends Error {
|
|
|
68
68
|
* it; the checkout's status follows the payment from there.
|
|
69
69
|
*/
|
|
70
70
|
export async function payWithWallet(wallet, quote) {
|
|
71
|
-
const
|
|
71
|
+
const hash = await sendTransfer(wallet, quoteTransfer(quote), quote.asset, quote.decimals);
|
|
72
|
+
submitWalletTransaction(quote, hash);
|
|
73
|
+
return hash;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Pays `amountAtomic` of a token to a customer's deposit address from a wallet, as `payWithWallet`
|
|
77
|
+
* pays a quote: connects, switches to (or adds) the network's chain, checks the token balance, and
|
|
78
|
+
* sends the ERC-20 `transfer` that the token's `payment_uri` states, for exactly that amount. Then,
|
|
79
|
+
* with `clientSecret` and `apiBase`, it hints the transaction to the service without waiting for
|
|
80
|
+
* or failing on it. Resolves with the transaction hash once the wallet has broadcast it; follow the
|
|
81
|
+
* payment in the address's `payments` by that hash.
|
|
82
|
+
*/
|
|
83
|
+
export async function payDepositAddressWithWallet(wallet, { network, asset, amountAtomic, clientSecret, apiBase }) {
|
|
84
|
+
if (amountAtomic <= 0n) {
|
|
85
|
+
throw new TypeError("amountAtomic must be positive");
|
|
86
|
+
}
|
|
87
|
+
const transfer = { ...depositAddressTransfer(network, asset), amount: amountAtomic };
|
|
88
|
+
const hash = await sendTransfer(wallet, transfer, asset.asset, asset.decimals);
|
|
89
|
+
if (clientSecret !== undefined && apiBase !== undefined) {
|
|
90
|
+
void submitTransaction({ apiBase, clientSecret, transactionHash: hash, chainId: transfer.chainId }).catch(() => undefined);
|
|
91
|
+
}
|
|
92
|
+
return hash;
|
|
93
|
+
}
|
|
94
|
+
async function sendTransfer(wallet, transfer, asset, decimals) {
|
|
72
95
|
const client = isWalletClient(wallet) ? wallet : createWalletClient({ transport: custom(wallet) });
|
|
73
96
|
try {
|
|
74
97
|
const account = client.account ?? (await client.requestAddresses())[0];
|
|
@@ -79,11 +102,11 @@ export async function payWithWallet(wallet, quote) {
|
|
|
79
102
|
const address = typeof account === "string" ? account : account.address;
|
|
80
103
|
const balance = await tokenBalance(client, transfer.token, address);
|
|
81
104
|
if (balance !== undefined && balance < transfer.amount) {
|
|
82
|
-
const symbol =
|
|
83
|
-
throw new WalletError("insufficient_balance", `Your wallet holds ${formatUnitsGrouped(balance,
|
|
84
|
-
`${
|
|
105
|
+
const symbol = asset.toUpperCase();
|
|
106
|
+
throw new WalletError("insufficient_balance", `Your wallet holds ${formatUnitsGrouped(balance, decimals)} ${symbol}, less than the ` +
|
|
107
|
+
`${formatUnitsGrouped(transfer.amount, decimals)} ${symbol} to pay. Nothing was sent.`);
|
|
85
108
|
}
|
|
86
|
-
|
|
109
|
+
return await client.writeContract({
|
|
87
110
|
account,
|
|
88
111
|
chain: knownChain(transfer.chainId) ?? null,
|
|
89
112
|
address: transfer.token,
|
|
@@ -91,8 +114,6 @@ export async function payWithWallet(wallet, quote) {
|
|
|
91
114
|
functionName: "transfer",
|
|
92
115
|
args: [transfer.to, transfer.amount],
|
|
93
116
|
});
|
|
94
|
-
submitWalletTransaction(quote, hash);
|
|
95
|
-
return hash;
|
|
96
117
|
}
|
|
97
118
|
catch (error) {
|
|
98
119
|
if (error instanceof WalletError) {
|
package/dist/wallet.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wallet.js","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"wallet.js","sourceRoot":"","sources":["../src/wallet.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/wallet.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { submitWalletTransaction } from "./transactions.js";
|
|
1
|
+
import { submitTransaction, submitWalletTransaction } from "./transactions.js";
|
|
2
2
|
import { createStore } from "mipd";
|
|
3
3
|
import {
|
|
4
4
|
BaseError,
|
|
@@ -13,8 +13,14 @@ import {
|
|
|
13
13
|
} from "viem";
|
|
14
14
|
import { readContract } from "viem/actions";
|
|
15
15
|
import { knownChain, networkName } from "./chains.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { formatUnitsGrouped } from "./format.js";
|
|
17
|
+
import {
|
|
18
|
+
depositAddressTransfer,
|
|
19
|
+
quoteTransfer,
|
|
20
|
+
type DepositAddressAsset,
|
|
21
|
+
type DepositAddressNetwork,
|
|
22
|
+
type TokenTransfer,
|
|
23
|
+
} from "./payment.js";
|
|
18
24
|
import type { ClientQuote } from "./quote.js";
|
|
19
25
|
|
|
20
26
|
/** EIP-6963 provider info. */
|
|
@@ -119,7 +125,58 @@ export async function payWithWallet(
|
|
|
119
125
|
wallet: WalletClient | EthereumProvider,
|
|
120
126
|
quote: ClientQuote,
|
|
121
127
|
): Promise<Hash> {
|
|
122
|
-
const
|
|
128
|
+
const hash = await sendTransfer(wallet, quoteTransfer(quote), quote.asset, quote.decimals);
|
|
129
|
+
submitWalletTransaction(quote, hash);
|
|
130
|
+
return hash;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface PayDepositAddressOptions {
|
|
134
|
+
/** The network to pay on, from the deposit address's `networks`. */
|
|
135
|
+
network: DepositAddressNetwork;
|
|
136
|
+
/** The token to pay in, from that network's `assets`. */
|
|
137
|
+
asset: DepositAddressAsset;
|
|
138
|
+
/** The token amount to send, in the smallest unit; positive. */
|
|
139
|
+
amountAtomic: bigint;
|
|
140
|
+
/**
|
|
141
|
+
* The address's `client_secret`. With `apiBase`, the transaction hash is sent to the service as
|
|
142
|
+
* a best-effort hint once the wallet broadcasts it, so the payment is found within about a block.
|
|
143
|
+
*/
|
|
144
|
+
clientSecret?: string | undefined;
|
|
145
|
+
/** The service origin; needed with `clientSecret`. */
|
|
146
|
+
apiBase?: string | undefined;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Pays `amountAtomic` of a token to a customer's deposit address from a wallet, as `payWithWallet`
|
|
151
|
+
* pays a quote: connects, switches to (or adds) the network's chain, checks the token balance, and
|
|
152
|
+
* sends the ERC-20 `transfer` that the token's `payment_uri` states, for exactly that amount. Then,
|
|
153
|
+
* with `clientSecret` and `apiBase`, it hints the transaction to the service without waiting for
|
|
154
|
+
* or failing on it. Resolves with the transaction hash once the wallet has broadcast it; follow the
|
|
155
|
+
* payment in the address's `payments` by that hash.
|
|
156
|
+
*/
|
|
157
|
+
export async function payDepositAddressWithWallet(
|
|
158
|
+
wallet: WalletClient | EthereumProvider,
|
|
159
|
+
{ network, asset, amountAtomic, clientSecret, apiBase }: PayDepositAddressOptions,
|
|
160
|
+
): Promise<Hash> {
|
|
161
|
+
if (amountAtomic <= 0n) {
|
|
162
|
+
throw new TypeError("amountAtomic must be positive");
|
|
163
|
+
}
|
|
164
|
+
const transfer = { ...depositAddressTransfer(network, asset), amount: amountAtomic };
|
|
165
|
+
const hash = await sendTransfer(wallet, transfer, asset.asset, asset.decimals);
|
|
166
|
+
if (clientSecret !== undefined && apiBase !== undefined) {
|
|
167
|
+
void submitTransaction({ apiBase, clientSecret, transactionHash: hash, chainId: transfer.chainId }).catch(
|
|
168
|
+
() => undefined,
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return hash;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function sendTransfer(
|
|
175
|
+
wallet: WalletClient | EthereumProvider,
|
|
176
|
+
transfer: TokenTransfer,
|
|
177
|
+
asset: string,
|
|
178
|
+
decimals: number,
|
|
179
|
+
): Promise<Hash> {
|
|
123
180
|
const client = isWalletClient(wallet) ? wallet : createWalletClient({ transport: custom(wallet) });
|
|
124
181
|
try {
|
|
125
182
|
const account = client.account ?? (await client.requestAddresses())[0];
|
|
@@ -130,14 +187,14 @@ export async function payWithWallet(
|
|
|
130
187
|
const address = typeof account === "string" ? account : account.address;
|
|
131
188
|
const balance = await tokenBalance(client, transfer.token, address);
|
|
132
189
|
if (balance !== undefined && balance < transfer.amount) {
|
|
133
|
-
const symbol =
|
|
190
|
+
const symbol = asset.toUpperCase();
|
|
134
191
|
throw new WalletError(
|
|
135
192
|
"insufficient_balance",
|
|
136
|
-
`Your wallet holds ${formatUnitsGrouped(balance,
|
|
137
|
-
`${
|
|
193
|
+
`Your wallet holds ${formatUnitsGrouped(balance, decimals)} ${symbol}, less than the ` +
|
|
194
|
+
`${formatUnitsGrouped(transfer.amount, decimals)} ${symbol} to pay. Nothing was sent.`,
|
|
138
195
|
);
|
|
139
196
|
}
|
|
140
|
-
|
|
197
|
+
return await client.writeContract({
|
|
141
198
|
account,
|
|
142
199
|
chain: knownChain(transfer.chainId) ?? null,
|
|
143
200
|
address: transfer.token,
|
|
@@ -145,8 +202,6 @@ export async function payWithWallet(
|
|
|
145
202
|
functionName: "transfer",
|
|
146
203
|
args: [transfer.to, transfer.amount],
|
|
147
204
|
});
|
|
148
|
-
submitWalletTransaction(quote, hash);
|
|
149
|
-
return hash;
|
|
150
205
|
} catch (error) {
|
|
151
206
|
if (error instanceof WalletError) {
|
|
152
207
|
throw error;
|