multicoyn-sdk 0.1.8 → 0.1.10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Multicoyn SDK
2
2
 
3
- A Web3 payment SDK for multichain crypto payments with support for multiple tokens and settlement options.
3
+ React SDK for multi-coin/multi-token payments with split allocation, auto-optimize, and multi-chain support (Lisk Sepolia). Includes a ready-to-use payment modal UI and wallet integration via RainbowKit/Wagmi.
4
4
 
5
5
  ## Installation
6
6
 
@@ -12,112 +12,258 @@ yarn add multicoyn-sdk
12
12
  pnpm add multicoyn-sdk
13
13
  ```
14
14
 
15
- ## Peer Dependencies
16
-
17
- Make sure you have the following peer dependencies installed:
18
-
15
+ ### Peer Dependencies
16
+ Make sure these are installed:
19
17
  ```bash
20
- npm install react react-dom viem wagmi @tanstack/react-query @rainbow-me/rainbowkit
18
+ npm install react react-dom wagmi viem @tanstack/react-query @rainbow-me/rainbowkit
21
19
  ```
22
20
 
23
- ## Usage
24
-
25
- ### 1. Setup Providers
26
-
27
- Wrap your app with the required providers:
21
+ ## Quick Start
28
22
 
29
23
  ```tsx
30
- import { Web3Provider, PaymentProvider } from 'multicoyn-sdk';
24
+ import { Web3Provider, PaymentProvider, MulticoynButton } from 'multicoyn-sdk';
31
25
  import 'multicoyn-sdk/styles';
32
26
 
27
+ const items = [{ name: 'Order #123', price: 100 }]; // price in selected currency (default USD)
28
+
33
29
  function App() {
34
30
  return (
35
31
  <Web3Provider>
36
32
  <PaymentProvider>
37
- <YourApp />
33
+ <MulticoynButton
34
+ merchantAddress="0xYourMerchantAddress"
35
+ items={items}
36
+ config={{ currency: 'USD' }} // or 'IDR'
37
+ onPaymentComplete={(result) => console.log('Success:', result)}
38
+ onPaymentError={(error) => console.error('Error:', error)}
39
+ />
38
40
  </PaymentProvider>
39
41
  </Web3Provider>
40
42
  );
41
43
  }
42
44
  ```
43
45
 
44
- ### 2. Use the Payment Button
46
+ ## Key Features
45
47
 
46
- ```tsx
47
- import { MulticoynButton, type PaymentConfig } from 'multicoyn-sdk';
48
+ - 🪙 **Multi-token split**: Users can allocate multiple tokens at once (ETH, USDC, USDT, DAI, WBTC)
49
+ - ⚖️ **Auto-optimize**: Automatically distributes allocation (prioritizes stablecoins if sufficient)
50
+ - 🔄 **Live price fetch**: Real-time token prices via on-chain TokenRegistry
51
+ - 🛡️ **Balance & price validation**: Verifies allocation covers total payment before submission
52
+ - 🧾 **Multi-item cart**: Supports multiple items with automatic total calculation
53
+ - 💱 **Multi-currency**: Supports USD and IDR pricing with automatic conversion
54
+ - 💸 **IDR Settlement**: Option to settle payments in IDRX stablecoin
55
+ - 🌐 **Wallet-ready**: RainbowKit + Wagmi + React Query pre-configured via `Web3Provider`
48
56
 
49
- function YourComponent() {
50
- const handlePaymentComplete = (result) => {
51
- console.log('Payment success:', result.transactionId);
52
- };
57
+ ## Supported Tokens
53
58
 
54
- const handlePaymentError = (error) => {
55
- console.error('Payment error:', error.message);
56
- };
59
+ | Token | Symbol | Use |
60
+ |-------|--------|-----|
61
+ | Ether | ETH | Payment |
62
+ | USD Coin | USDC | Payment |
63
+ | Tether USD | USDT | Payment |
64
+ | Dai Stablecoin | DAI | Payment |
65
+ | Wrapped Bitcoin | WBTC | Payment |
66
+ | Indonesian Rupiah | IDRX | Settlement only |
57
67
 
58
- return (
59
- <MulticoynButton
60
- totalAmount={100}
61
- merchantAddress="0x..."
62
- items={[
63
- { name: "Product 1", price: 50 },
64
- { name: "Product 2", price: 50 }
65
- ]}
66
- currency="USD" // or "IDR" - automatically determines settlement currency
67
- onPaymentComplete={handlePaymentComplete}
68
- onPaymentError={handlePaymentError}
69
- />
70
- );
68
+ ## Components & API
69
+
70
+ ### `<MulticoynButton />`
71
+
72
+ Main button component that opens the payment modal.
73
+
74
+ ```ts
75
+ interface MulticoynButtonProps {
76
+ merchantAddress: `0x${string}`; // Merchant wallet address
77
+ items: PaymentItem[]; // Cart items
78
+ config?: PaymentConfig; // Payment configuration
79
+ onPaymentComplete?: (result: PaymentResult) => void;
80
+ onPaymentError?: (error: Error) => void;
81
+ className?: string; // Custom button styling
82
+ children?: React.ReactNode; // Custom button content
83
+ }
84
+
85
+ interface PaymentItem {
86
+ name: string;
87
+ price: number; // Price in selected currency
88
+ }
89
+
90
+ interface PaymentConfig {
91
+ currency?: 'USD' | 'IDR'; // Default: 'USD'
92
+ target?: `0x${string}`; // Optional: target contract for callback
93
+ callData?: `0x${string}`; // Optional: calldata for router callback
71
94
  }
72
95
  ```
73
96
 
74
- #### Advanced Usage with Smart Contract Interaction
97
+ #### Payment Result
75
98
 
76
- ```tsx
77
- <MulticoynButton
78
- totalAmount={100}
79
- merchantAddress="0x..."
80
- items={[{ name: "NFT Mint", price: 100 }]}
81
- currency="USD" // or "IDR" - automatically determines settlement currency
82
- // Optional: Execute custom contract call after payment
83
- target="0xNFTContractAddress"
84
- callData="0x..." // encoded function call
85
- onPaymentComplete={handlePaymentComplete}
86
- onPaymentError={handlePaymentError}
87
- />
99
+ ```ts
100
+ interface PaymentResult {
101
+ success: boolean;
102
+ transactionId?: string; // Transaction hash
103
+ tokens: Token[]; // Tokens used in payment
104
+ }
105
+
106
+ interface Token {
107
+ id: string;
108
+ name: string;
109
+ symbol: string;
110
+ amount: number; // User's balance
111
+ chain: string;
112
+ percentage: number; // Allocation percentage (0-100)
113
+ address: `0x${string}`;
114
+ decimals: number;
115
+ priceUSD: number;
116
+ }
88
117
  ```
89
118
 
90
- ### 3. Access Payment Configuration
119
+ ### Providers
120
+
121
+ #### `<Web3Provider>`
122
+ Wraps your app with Wagmi, RainbowKit, and React Query providers.
91
123
 
92
124
  ```tsx
93
- import { usePaymentConfig } from 'multicoyn-sdk';
125
+ <Web3Provider>
126
+ {/* Your app */}
127
+ </Web3Provider>
128
+ ```
129
+
130
+ #### `<PaymentProvider>`
131
+ Optional provider for global payment configuration.
94
132
 
95
- function YourComponent() {
96
- const config = usePaymentConfig();
97
- // Access payment configuration and state
133
+ ```tsx
134
+ interface PaymentConfig {
135
+ merchantAddress?: `0x${string}`;
136
+ settleInIDR?: boolean;
137
+ enabledTokens?: string[];
138
+ theme?: 'light' | 'dark';
98
139
  }
140
+
141
+ <PaymentProvider initialConfig={{ theme: 'dark' }}>
142
+ {/* Your app */}
143
+ </PaymentProvider>
99
144
  ```
100
145
 
101
- ## Features
146
+ #### `usePaymentConfig()`
147
+ Hook to access and update payment configuration at runtime.
102
148
 
103
- - Multi-chain payment support
104
- - Multiple token options (USDC, USDT, DAI, WBTC, Native tokens)
105
- - Settlement token support (IDRX)
106
- - Built-in wallet connection via RainbowKit
107
- - TypeScript support
108
- - Tailwind CSS styling
149
+ ```tsx
150
+ const { config, updateConfig } = usePaymentConfig();
151
+ updateConfig({ settleInIDR: true });
152
+ ```
109
153
 
110
- ## Configuration
154
+ ### Hooks
111
155
 
112
- The SDK comes with pre-configured contracts and chains. You can also access these configurations:
156
+ Available hooks for advanced usage:
157
+
158
+ | Hook | Description |
159
+ |------|-------------|
160
+ | `usePaymentModal` | Control payment modal state |
161
+ | `usePaymentRouter` | Execute payments & check transaction status |
162
+ | `useTokenRegistry` | Fetch token prices from on-chain registry |
163
+ | `useMultiTokenBalances` | Get user balances for all supported tokens |
164
+ | `useMultiTokenPrices` | Get current prices for all supported tokens |
165
+ | `useERC20` | Generic ERC20 token operations |
166
+
167
+ #### Example: usePaymentRouter
113
168
 
114
169
  ```tsx
115
- import { CONTRACTS, TOKENS, liskSepolia } from 'multicoyn-sdk';
170
+ const {
171
+ executePayment, // Execute payment transaction
172
+ hash, // Transaction hash
173
+ isPending, // Transaction pending
174
+ isConfirming, // Waiting for confirmation
175
+ isConfirmed, // Transaction confirmed
176
+ error // Error if any
177
+ } = usePaymentRouter();
178
+ ```
116
179
 
117
- console.log(CONTRACTS.PAYMENT_ROUTER);
118
- console.log(TOKENS.USDC);
180
+ ### Configuration & Constants
181
+
182
+ ```ts
183
+ import {
184
+ CONTRACTS, // Contract addresses
185
+ TOKENS, // Token addresses
186
+ wagmiConfig, // Wagmi configuration
187
+ liskSepolia, // Chain config
188
+ FEE_PERCENTAGE, // 0.003 (0.3%)
189
+ USD_SCALE, // 1e8
190
+ TOKEN_METADATA // Token info (symbol, decimals, name)
191
+ } from 'multicoyn-sdk';
192
+ ```
193
+
194
+ #### Contract Addresses (Lisk Sepolia)
195
+
196
+ ```ts
197
+ CONTRACTS = {
198
+ PAYMENT_ROUTER: "0x73Dbc7447E3B097cFc8b08ee7896a9D27D67e2B4",
199
+ TOKEN_REGISTRY: "0x1d2C6dfB2f127d6F3c14859c9E54cbc27bd7FcCE"
200
+ }
201
+
202
+ TOKENS = {
203
+ NATIVE: "0x0000000000000000000000000000000000000000", // ETH
204
+ USDC: "0x0Ff0aED4862e168086FD8BC38a4c27cE1830228b",
205
+ USDT: "0xBc63b0cf19b757c2a6Ef646027f8CeA7Af2c3e7F",
206
+ DAI: "0xd2aAa24D5C305B7968e955A89F0bf4E7776E7078",
207
+ WBTC: "0x1BEC7ec7F995B9bcd93F411B2cE7d289C6b05f03",
208
+ IDRX: "0x39B9205cDC53114c0B0F22F04C1215A13197b4d9" // Settlement
209
+ }
210
+ ```
211
+
212
+ ## Styling
213
+
214
+ Import the styles once in your app:
215
+
216
+ ```tsx
217
+ import 'multicoyn-sdk/styles';
218
+ // or
219
+ import 'multicoyn-sdk/dist/multicoyn-sdk.css';
220
+ ```
221
+
222
+ - No Tailwind setup required in host app (CSS is bundled)
223
+ - All classes are prefixed with `mc:` to prevent conflicts
224
+
225
+ ## Payment Flow
226
+
227
+ 1. User clicks the MulticoynButton
228
+ 2. If not connected, wallet connection is triggered
229
+ 3. Payment modal opens showing user's token balances
230
+ 4. User allocates tokens (manually or via auto-optimize)
231
+ 5. Total allocation must equal 100%
232
+ 6. User submits payment
233
+ 7. SDK handles token approvals automatically
234
+ 8. Payment is executed via PaymentRouter contract
235
+ 9. Transaction confirmation triggers `onPaymentComplete` callback
236
+
237
+ ## Validation Rules
238
+
239
+ - ✅ Total token allocation must equal 100%
240
+ - ✅ Token prices must be available from registry
241
+ - ✅ User must have sufficient balance for selected allocation
242
+ - ❌ Button disabled if any validation fails
243
+
244
+ ## Fees
245
+
246
+ - Platform fee: **0.3%** (automatically added to payment)
247
+ - Fee is calculated on top of the product price
248
+
249
+ ## Build & Development
250
+
251
+ ```bash
252
+ npm run dev # Start development server
253
+ npm run build # Build library (dist/)
254
+ npm run build:lib # Build with type declarations
255
+ npm run lint # Run ESLint
119
256
  ```
120
257
 
258
+ ## Requirements
259
+
260
+ - Node.js 20.19+ (Vite 7)
261
+ - React 18 or 19
262
+
263
+ ## Network
264
+
265
+ Currently deployed on **Lisk Sepolia** testnet.
266
+
121
267
  ## License
122
268
 
123
269
  MIT
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-Daw_yCWZ.cjs");function k(r){const{abi:n,data:a}=r,o=e.slice(a,0,4),t=n.find(s=>s.type==="function"&&o===e.toFunctionSelector(e.formatAbiItem(s)));if(!t)throw new e.AbiFunctionSignatureNotFoundError(o,{docsPath:"/docs/contract/decodeFunctionData"});return{functionName:t.name,args:"inputs"in t&&t.inputs&&t.inputs.length>0?e.decodeAbiParameters(t.inputs,e.slice(a,4)):void 0}}const h="/docs/contract/encodeErrorResult";function y(r){const{abi:n,errorName:a,args:o}=r;let t=n[0];if(a){const f=e.getAbiItem({abi:n,args:o,name:a});if(!f)throw new e.AbiErrorNotFoundError(a,{docsPath:h});t=f}if(t.type!=="error")throw new e.AbiErrorNotFoundError(void 0,{docsPath:h});const s=e.formatAbiItem(t),c=e.toFunctionSelector(s);let i="0x";if(o&&o.length>0){if(!t.inputs)throw new e.AbiErrorInputsNotFoundError(t.name,{docsPath:h});i=e.encodeAbiParameters(t.inputs,o)}return e.concatHex([c,i])}const m="/docs/contract/encodeFunctionResult";function L(r){const{abi:n,functionName:a,result:o}=r;let t=n[0];if(a){const c=e.getAbiItem({abi:n,name:a});if(!c)throw new e.AbiFunctionNotFoundError(a,{docsPath:m});t=c}if(t.type!=="function")throw new e.AbiFunctionNotFoundError(void 0,{docsPath:m});if(!t.outputs)throw new e.AbiFunctionOutputsNotFoundError(t.name,{docsPath:m});const s=(()=>{if(t.outputs.length===0)return[];if(t.outputs.length===1)return[o];if(Array.isArray(o))return o;throw new e.InvalidArrayError(o)})();return e.encodeAbiParameters(t.outputs,s)}const b="x-batch-gateway:true";async function g(r){const{data:n,ccipRequest:a}=r,{args:[o]}=k({abi:e.batchGatewayAbi,data:n}),t=[],s=[];return await Promise.all(o.map(async(c,i)=>{try{s[i]=c.urls.includes(b)?await g({data:c.data,ccipRequest:a}):await a(c),t[i]=!1}catch(f){t[i]=!0,s[i]=F(f)}})),L({abi:e.batchGatewayAbi,functionName:"query",result:[t,s]})}function F(r){return r.name==="HttpRequestError"&&r.status?y({abi:e.batchGatewayAbi,errorName:"HttpError",args:[r.status,r.shortMessage]}):y({abi:[e.solidityError],errorName:"Error",args:["shortMessage"in r?r.shortMessage:r.message]})}function O(r,n){if(!e.isAddress(r,{strict:!1}))throw new e.InvalidAddressError({address:r});if(!e.isAddress(n,{strict:!1}))throw new e.InvalidAddressError({address:n});return r.toLowerCase()===n.toLowerCase()}class P extends e.BaseError{constructor({callbackSelector:n,cause:a,data:o,extraData:t,sender:s,urls:c}){super(a.shortMessage||"An error occurred while fetching for an offchain result.",{cause:a,metaMessages:[...a.metaMessages||[],a.metaMessages?.length?"":[],"Offchain Gateway Call:",c&&[" Gateway URL(s):",...c.map(i=>` ${e.getUrl(i)}`)],` Sender: ${s}`,` Data: ${o}`,` Callback selector: ${n}`,` Extra data: ${t}`].flat(),name:"OffchainLookupError"})}}class S extends e.BaseError{constructor({result:n,url:a}){super("Offchain gateway response is malformed. Response data must be a hex value.",{metaMessages:[`Gateway URL: ${e.getUrl(a)}`,`Response: ${e.stringify(n)}`],name:"OffchainLookupResponseMalformedError"})}}class x extends e.BaseError{constructor({sender:n,to:a}){super("Reverted sender address does not match target contract address (`to`).",{metaMessages:[`Contract address: ${a}`,`OffchainLookup sender address: ${n}`],name:"OffchainLookupSenderMismatchError"})}}const M="0x556f1830",E={name:"OffchainLookup",type:"error",inputs:[{name:"sender",type:"address"},{name:"urls",type:"string[]"},{name:"callData",type:"bytes"},{name:"callbackFunction",type:"bytes4"},{name:"extraData",type:"bytes"}]};async function N(r,{blockNumber:n,blockTag:a,data:o,to:t}){const{args:s}=e.decodeErrorResult({data:o,abi:[E]}),[c,i,f,u,d]=s,{ccipRead:l}=r,w=l&&typeof l?.request=="function"?l.request:A;try{if(!O(t,c))throw new x({sender:c,to:t});const p=i.includes(b)?await g({data:f,ccipRequest:w}):await w({data:f,sender:c,urls:i}),{data:R}=await e.call(r,{blockNumber:n,blockTag:a,data:e.concat([u,e.encodeAbiParameters([{type:"bytes"},{type:"bytes"}],[p,d])]),to:t});return R}catch(p){throw new P({callbackSelector:u,cause:p,data:o,extraData:d,sender:c,urls:i})}}async function A({data:r,sender:n,urls:a}){let o=new Error("An unknown error occurred.");for(let t=0;t<a.length;t++){const s=a[t],c=s.includes("{data}")?"GET":"POST",i=c==="POST"?{data:r,sender:n}:void 0,f=c==="POST"?{"Content-Type":"application/json"}:{};try{const u=await fetch(s.replace("{sender}",n.toLowerCase()).replace("{data}",r),{body:JSON.stringify(i),headers:f,method:c});let d;if(u.headers.get("Content-Type")?.startsWith("application/json")?d=(await u.json()).data:d=await u.text(),!u.ok){o=new e.HttpRequestError({body:i,details:d?.error?e.stringify(d.error):u.statusText,headers:u.headers,status:u.status,url:s});continue}if(!e.isHex(d)){o=new S({result:d,url:s});continue}return d}catch(u){o=new e.HttpRequestError({body:i,details:u.message,url:s})}}throw o}exports.ccipRequest=A;exports.offchainLookup=N;exports.offchainLookupAbiItem=E;exports.offchainLookupSignature=M;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-BYCRbJsO.cjs");function k(r){const{abi:n,data:a}=r,o=e.slice(a,0,4),t=n.find(s=>s.type==="function"&&o===e.toFunctionSelector(e.formatAbiItem(s)));if(!t)throw new e.AbiFunctionSignatureNotFoundError(o,{docsPath:"/docs/contract/decodeFunctionData"});return{functionName:t.name,args:"inputs"in t&&t.inputs&&t.inputs.length>0?e.decodeAbiParameters(t.inputs,e.slice(a,4)):void 0}}const h="/docs/contract/encodeErrorResult";function y(r){const{abi:n,errorName:a,args:o}=r;let t=n[0];if(a){const f=e.getAbiItem({abi:n,args:o,name:a});if(!f)throw new e.AbiErrorNotFoundError(a,{docsPath:h});t=f}if(t.type!=="error")throw new e.AbiErrorNotFoundError(void 0,{docsPath:h});const s=e.formatAbiItem(t),c=e.toFunctionSelector(s);let i="0x";if(o&&o.length>0){if(!t.inputs)throw new e.AbiErrorInputsNotFoundError(t.name,{docsPath:h});i=e.encodeAbiParameters(t.inputs,o)}return e.concatHex([c,i])}const m="/docs/contract/encodeFunctionResult";function L(r){const{abi:n,functionName:a,result:o}=r;let t=n[0];if(a){const c=e.getAbiItem({abi:n,name:a});if(!c)throw new e.AbiFunctionNotFoundError(a,{docsPath:m});t=c}if(t.type!=="function")throw new e.AbiFunctionNotFoundError(void 0,{docsPath:m});if(!t.outputs)throw new e.AbiFunctionOutputsNotFoundError(t.name,{docsPath:m});const s=(()=>{if(t.outputs.length===0)return[];if(t.outputs.length===1)return[o];if(Array.isArray(o))return o;throw new e.InvalidArrayError(o)})();return e.encodeAbiParameters(t.outputs,s)}const b="x-batch-gateway:true";async function g(r){const{data:n,ccipRequest:a}=r,{args:[o]}=k({abi:e.batchGatewayAbi,data:n}),t=[],s=[];return await Promise.all(o.map(async(c,i)=>{try{s[i]=c.urls.includes(b)?await g({data:c.data,ccipRequest:a}):await a(c),t[i]=!1}catch(f){t[i]=!0,s[i]=F(f)}})),L({abi:e.batchGatewayAbi,functionName:"query",result:[t,s]})}function F(r){return r.name==="HttpRequestError"&&r.status?y({abi:e.batchGatewayAbi,errorName:"HttpError",args:[r.status,r.shortMessage]}):y({abi:[e.solidityError],errorName:"Error",args:["shortMessage"in r?r.shortMessage:r.message]})}function O(r,n){if(!e.isAddress(r,{strict:!1}))throw new e.InvalidAddressError({address:r});if(!e.isAddress(n,{strict:!1}))throw new e.InvalidAddressError({address:n});return r.toLowerCase()===n.toLowerCase()}class P extends e.BaseError{constructor({callbackSelector:n,cause:a,data:o,extraData:t,sender:s,urls:c}){super(a.shortMessage||"An error occurred while fetching for an offchain result.",{cause:a,metaMessages:[...a.metaMessages||[],a.metaMessages?.length?"":[],"Offchain Gateway Call:",c&&[" Gateway URL(s):",...c.map(i=>` ${e.getUrl(i)}`)],` Sender: ${s}`,` Data: ${o}`,` Callback selector: ${n}`,` Extra data: ${t}`].flat(),name:"OffchainLookupError"})}}class S extends e.BaseError{constructor({result:n,url:a}){super("Offchain gateway response is malformed. Response data must be a hex value.",{metaMessages:[`Gateway URL: ${e.getUrl(a)}`,`Response: ${e.stringify(n)}`],name:"OffchainLookupResponseMalformedError"})}}class x extends e.BaseError{constructor({sender:n,to:a}){super("Reverted sender address does not match target contract address (`to`).",{metaMessages:[`Contract address: ${a}`,`OffchainLookup sender address: ${n}`],name:"OffchainLookupSenderMismatchError"})}}const M="0x556f1830",E={name:"OffchainLookup",type:"error",inputs:[{name:"sender",type:"address"},{name:"urls",type:"string[]"},{name:"callData",type:"bytes"},{name:"callbackFunction",type:"bytes4"},{name:"extraData",type:"bytes"}]};async function N(r,{blockNumber:n,blockTag:a,data:o,to:t}){const{args:s}=e.decodeErrorResult({data:o,abi:[E]}),[c,i,f,u,d]=s,{ccipRead:l}=r,w=l&&typeof l?.request=="function"?l.request:A;try{if(!O(t,c))throw new x({sender:c,to:t});const p=i.includes(b)?await g({data:f,ccipRequest:w}):await w({data:f,sender:c,urls:i}),{data:R}=await e.call(r,{blockNumber:n,blockTag:a,data:e.concat([u,e.encodeAbiParameters([{type:"bytes"},{type:"bytes"}],[p,d])]),to:t});return R}catch(p){throw new P({callbackSelector:u,cause:p,data:o,extraData:d,sender:c,urls:i})}}async function A({data:r,sender:n,urls:a}){let o=new Error("An unknown error occurred.");for(let t=0;t<a.length;t++){const s=a[t],c=s.includes("{data}")?"GET":"POST",i=c==="POST"?{data:r,sender:n}:void 0,f=c==="POST"?{"Content-Type":"application/json"}:{};try{const u=await fetch(s.replace("{sender}",n.toLowerCase()).replace("{data}",r),{body:JSON.stringify(i),headers:f,method:c});let d;if(u.headers.get("Content-Type")?.startsWith("application/json")?d=(await u.json()).data:d=await u.text(),!u.ok){o=new e.HttpRequestError({body:i,details:d?.error?e.stringify(d.error):u.statusText,headers:u.headers,status:u.status,url:s});continue}if(!e.isHex(d)){o=new S({result:d,url:s});continue}return d}catch(u){o=new e.HttpRequestError({body:i,details:u.message,url:s})}}throw o}exports.ccipRequest=A;exports.offchainLookup=N;exports.offchainLookupAbiItem=E;exports.offchainLookupSignature=M;
@@ -1,4 +1,4 @@
1
- import { s as b, t as x, f as F, A as I, d as C, g as M, a as E, b as D, e as w, c as G, h as A, i as T, I as H, j as m, k as v, l as R, m as k, B as y, n as N, o as P, p as j, q as B, r as U, H as L, u as _ } from "./index-C1S0YnyW.js";
1
+ import { s as b, t as x, f as F, A as I, d as C, g as M, a as E, b as D, e as w, c as G, h as A, i as T, I as H, j as m, k as v, l as R, m as k, B as y, n as N, o as P, p as j, q as B, r as U, H as L, u as _ } from "./index-CKIs5Pi7.js";
2
2
  function J(e) {
3
3
  const { abi: s, data: a } = e, r = b(a, 0, 4), t = s.find((n) => n.type === "function" && r === x(F(n)));
4
4
  if (!t)
@@ -1,4 +1,4 @@
1
- import type { Token, PaymentItem } from "./types";
1
+ import type { PaymentItem, Token } from "./types";
2
2
  interface PaymentModalProps {
3
3
  isOpen: boolean;
4
4
  onClose: () => void;
@@ -11,7 +11,8 @@ interface PaymentModalProps {
11
11
  transactionHash?: string;
12
12
  isProcessing?: boolean;
13
13
  isSuccess?: boolean;
14
+ isError?: boolean;
14
15
  conversionRate?: number;
15
16
  }
16
- export declare function PaymentModal({ isOpen, onClose, totalAmount, currency, items, tokens: initialTokens, onPaymentSubmit, fee, transactionHash, isProcessing: externalIsProcessing, isSuccess: externalIsSuccess, conversionRate, }: PaymentModalProps): import("react").ReactPortal | null;
17
+ export declare function PaymentModal({ isOpen, onClose, totalAmount, currency, items, tokens: initialTokens, onPaymentSubmit, fee, transactionHash, isProcessing: externalIsProcessing, isSuccess: externalIsSuccess, isError: externalIsError, conversionRate, }: PaymentModalProps): import("react").ReactPortal | null;
17
18
  export {};
@@ -9,30 +9,36 @@ export declare const TOKEN_METADATA: {
9
9
  readonly symbol: "ETH";
10
10
  readonly decimals: 18;
11
11
  readonly name: "Ether";
12
+ readonly logo: "https://cryptologos.cc/logos/ethereum-eth-logo.svg";
12
13
  };
13
14
  readonly USDC: {
14
15
  readonly symbol: "USDC";
15
16
  readonly decimals: 6;
16
17
  readonly name: "USD Coin";
18
+ readonly logo: "https://cryptologos.cc/logos/usd-coin-usdc-logo.svg";
17
19
  };
18
20
  readonly USDT: {
19
21
  readonly symbol: "USDT";
20
22
  readonly decimals: 6;
21
23
  readonly name: "Tether USD";
24
+ readonly logo: "https://cryptologos.cc/logos/tether-usdt-logo.svg";
22
25
  };
23
26
  readonly DAI: {
24
27
  readonly symbol: "DAI";
25
28
  readonly decimals: 18;
26
29
  readonly name: "Dai Stablecoin";
30
+ readonly logo: "https://cryptologos.cc/logos/multi-collateral-dai-dai-logo.svg";
27
31
  };
28
32
  readonly WBTC: {
29
33
  readonly symbol: "WBTC";
30
34
  readonly decimals: 8;
31
35
  readonly name: "Wrapped Bitcoin";
36
+ readonly logo: "https://cryptologos.cc/logos/wrapped-bitcoin-wbtc-logo.svg";
32
37
  };
33
38
  readonly IDRX: {
34
39
  readonly symbol: "IDRX";
35
40
  readonly decimals: 18;
36
41
  readonly name: "Indonesian Rupiah";
42
+ readonly logo: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png";
37
43
  };
38
44
  };