deserialize-deposit-widget 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/README.md +146 -0
- package/dist/PayWithTokenWidget.d.ts +27 -0
- package/dist/PayWithTokenWidget.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/style.css +1 -0
- package/dist/swap-widget.cjs +1 -0
- package/dist/swap-widget.js +564 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# defungiz-swap-widget
|
|
2
|
+
|
|
3
|
+
A drop-in React / Next.js widget that lets users pay a fixed USD amount on the **0G network** using any ERC-20 token (or native OG) in their wallet. The widget handles token discovery, live price fetching, swap routing, transaction signing, and network switching — you just provide a provider and a callback.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install deserialize-deposit-widget
|
|
11
|
+
# or
|
|
12
|
+
yarn add deserialize-deposit-widget
|
|
13
|
+
# or
|
|
14
|
+
pnpm add deserialize-deposit-widget
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { BrowserProvider } from "ethers";
|
|
23
|
+
import { PayWithTokenWidget } from "pay-with-token-widget";
|
|
24
|
+
|
|
25
|
+
function MyPage() {
|
|
26
|
+
const [provider, setProvider] = useState<BrowserProvider | null>(null);
|
|
27
|
+
|
|
28
|
+
const connect = async () => {
|
|
29
|
+
const p = new BrowserProvider(window.ethereum);
|
|
30
|
+
await p.send("eth_requestAccounts", []);
|
|
31
|
+
setProvider(p);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const handleMint = async () => {
|
|
35
|
+
// call your NFT contract here
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<>
|
|
40
|
+
<button onClick={connect}>Connect Wallet</button>
|
|
41
|
+
|
|
42
|
+
{provider && (
|
|
43
|
+
<PayWithTokenWidget
|
|
44
|
+
provider={provider}
|
|
45
|
+
usdAmount="5"
|
|
46
|
+
allowedTokens="all"
|
|
47
|
+
onExecuteNftAction={handleMint}
|
|
48
|
+
onError={(err) => console.error(err)}
|
|
49
|
+
/>
|
|
50
|
+
)}
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Props
|
|
59
|
+
|
|
60
|
+
| Prop | Type | Required | Default | Description |
|
|
61
|
+
| -------------------- | ------------------------------------ | -------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| `provider` | `BrowserProvider` | ✅ | — | An ethers v6 `BrowserProvider` connected to the user's wallet. |
|
|
63
|
+
| `usdAmount` | `string` | ✅ | — | The fixed USD amount the user must pay, e.g. `"5"` or `"0.50"`. |
|
|
64
|
+
| `allowedTokens` | `"all"` \| `string[]` | ✅ | — | Which tokens to show. Pass `"all"` to show every supported token, or an array of ERC-20 contract addresses to restrict the list. Include the native sentinel address (`0xEeee…EEEE`) in the array to add the native OG token. |
|
|
65
|
+
| `onExecuteNftAction` | `() => Promise<void>` | ✅ | — | Called after the swap transactions confirm. Use this to mint/buy your NFT or execute whatever action the payment unlocks. |
|
|
66
|
+
| `onError` | `(err: unknown) => void` | — | — | Called whenever an error occurs (wrong network, insufficient funds, rejected transaction, API failure, etc.). |
|
|
67
|
+
| `slippageBps` | `number` | — | `100` | Swap slippage tolerance in basis points. `100` = 1 %. |
|
|
68
|
+
| `partnerFees` | `{ fee: number; recipient: string }` | — | — | Optional protocol fee. `fee` is in basis points; `recipient` is the fee-receiving address. |
|
|
69
|
+
| `accentColor` | `string` | — | `"#ab03b6"` | Hex colour used to theme the entire widget — button, borders, focus rings, and card background. Non-hex values (e.g. `"royalblue"`) are applied to the button only. |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## `allowedTokens` examples
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
// Show every token the API knows about + native OG
|
|
77
|
+
<PayWithTokenWidget allowedTokens="all" ... />
|
|
78
|
+
|
|
79
|
+
// Restrict to two specific ERC-20s
|
|
80
|
+
<PayWithTokenWidget
|
|
81
|
+
allowedTokens={[
|
|
82
|
+
"0x7bbc63d01ca42491c3e084c941c3e86e55951404",
|
|
83
|
+
"0xabc123...",
|
|
84
|
+
]}
|
|
85
|
+
...
|
|
86
|
+
/>
|
|
87
|
+
|
|
88
|
+
// Native OG only
|
|
89
|
+
<PayWithTokenWidget
|
|
90
|
+
allowedTokens={["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]}
|
|
91
|
+
...
|
|
92
|
+
/>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
> **Important — Next.js / inline arrays:** If you pass `allowedTokens` as an inline array literal, wrap it in `useMemo` (or define it outside the component) so the reference stays stable and avoids re-fetching on every render.
|
|
96
|
+
>
|
|
97
|
+
> ```tsx
|
|
98
|
+
> const tokens = useMemo(
|
|
99
|
+
> () => ["0x7bbc63d01ca42491c3e084c941c3e86e55951404"],
|
|
100
|
+
> [],
|
|
101
|
+
> );
|
|
102
|
+
> <PayWithTokenWidget allowedTokens={tokens} ... />
|
|
103
|
+
> ```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Theming
|
|
108
|
+
|
|
109
|
+
Pass a single hex colour to `accentColor` and the widget derives the full palette automatically — button gradient, focus rings, and a dark card background tinted with your colour.
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
// Purple (default)
|
|
113
|
+
<PayWithTokenWidget accentColor="#ab03b6" ... />
|
|
114
|
+
|
|
115
|
+
// Blue
|
|
116
|
+
<PayWithTokenWidget accentColor="#015198" ... />
|
|
117
|
+
|
|
118
|
+
// Orange
|
|
119
|
+
<PayWithTokenWidget accentColor="#e85d04" ... />
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The widget is `width: 100%` by default and adapts to whatever container you place it in. Font is **Urbanist** (loaded automatically via Google Fonts).
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Network
|
|
127
|
+
|
|
128
|
+
The widget is hardcoded to the **0G Newton** network (chain ID `16661`). If the user's wallet is on a different network, a "Wrong network" banner appears with a one-click **Switch to 0G** button. If the network isn't in the wallet yet, the widget calls `wallet_addEthereumChain` automatically.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Flow
|
|
133
|
+
|
|
134
|
+
1. Widget loads supported tokens and their USD prices from the Deserialize API.
|
|
135
|
+
2. User selects a token — their balance and its USD equivalent are shown.
|
|
136
|
+
3. User clicks **Pay $X** — the widget fetches a swap quote, sends the transaction(s), and waits for confirmation.
|
|
137
|
+
4. Once confirmed, `onExecuteNftAction` is called so you can complete your mint / purchase.
|
|
138
|
+
5. Status messages (loading, errors, success) auto-clear after 3 seconds.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Requirements
|
|
143
|
+
|
|
144
|
+
- React 18+
|
|
145
|
+
- ethers v6
|
|
146
|
+
- A browser wallet (MetaMask, Rabby, etc.)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { BrowserProvider } from "ethers";
|
|
3
|
+
import "./pay-with-token-widget.css";
|
|
4
|
+
type PartnerFees = {
|
|
5
|
+
fee: number;
|
|
6
|
+
recipient: string;
|
|
7
|
+
};
|
|
8
|
+
export type PayWithTokenWidgetProps = {
|
|
9
|
+
provider: BrowserProvider;
|
|
10
|
+
usdAmount: string;
|
|
11
|
+
allowedTokens: "all" | string[];
|
|
12
|
+
slippageBps?: number;
|
|
13
|
+
partnerFees?: PartnerFees;
|
|
14
|
+
onExecuteAction: () => Promise<void>;
|
|
15
|
+
onError?: (err: unknown) => void;
|
|
16
|
+
accentColor?: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function PayWithTokenWidget({ provider, usdAmount, allowedTokens, slippageBps, partnerFees, onExecuteAction, onError, accentColor, }: PayWithTokenWidgetProps): React.JSX.Element;
|
|
19
|
+
export declare const PAY_WITH_TOKEN_WIDGET_CONSTANTS: {
|
|
20
|
+
API_BASE_URL: string;
|
|
21
|
+
FALLBACK_RPC: string;
|
|
22
|
+
NETWORK_ID: string;
|
|
23
|
+
REQUIRED_CHAIN_ID: number;
|
|
24
|
+
NATIVE_SENTINEL: string;
|
|
25
|
+
};
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=PayWithTokenWidget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PayWithTokenWidget.d.ts","sourceRoot":"","sources":["../src/PayWithTokenWidget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AACf,OAAO,EACL,eAAe,EAKhB,MAAM,QAAQ,CAAC;AAChB,OAAO,6BAA6B,CAAC;AAoBrC,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AA2BF,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAyQF,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,SAAS,EACT,aAAa,EACb,WAAiB,EACjB,WAAW,EACX,eAAe,EACf,OAAO,EACP,WAAW,GACZ,EAAE,uBAAuB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CA8hB7C;AAED,eAAO,MAAM,+BAA+B;;;;;;CAM3C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AAC3F,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=Urbanist:wght@400;600;700;800&display=swap";.pwt-root{--pwt-font: "Urbanist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--pwt-primary: #ab03b6;--pwt-primary-dim: #8d029a;--pwt-primary-lit: #c804d6;--pwt-primary-glow: rgba(171, 3, 182, .22);--pwt-primary-text: #ffffff;--pwt-bg: #ffffff;--pwt-surface: #faf7fc;--pwt-border: #e4d5eb;--pwt-border-focus: #ab03b6;--pwt-text: #1a0d1e;--pwt-muted: #7b6685;--pwt-success-text: #166534;--pwt-error-text: #b91c1c;--pwt-error-bg: rgba(185, 28, 28, .07);--pwt-error-border: #b91c1c;--pwt-radius-sm: 8px;--pwt-radius-md: 12px;--pwt-radius-lg: 20px;--pwt-radius-pill: 9999px;--pwt-ease: cubic-bezier(.4, 0, .2, 1);--pwt-t: .15s;display:flex;flex-direction:column;gap:10px;padding:22px 20px 18px;width:100%;background:var(--pwt-bg);border:1px solid var(--pwt-border);border-radius:var(--pwt-radius-lg);box-shadow:0 1px 2px #ab03b60d,0 4px 20px #00000012;font-family:var(--pwt-font);color:var(--pwt-text);box-sizing:border-box}@media (prefers-color-scheme: dark){.pwt-root{--pwt-bg: #120c17;--pwt-surface: #1d1425;--pwt-border: #382048;--pwt-text: #ede0f5;--pwt-muted: #9d88ab;--pwt-primary-glow: rgba(171, 3, 182, .3);--pwt-success-text: #4ade80;--pwt-error-text: #f87171;--pwt-error-bg: rgba(248, 113, 113, .1);--pwt-error-border: #f87171;box-shadow:0 1px 2px #00000080,0 4px 24px #ab03b624}}.pwt-label{display:block;font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--pwt-muted)}.pwt-row{display:flex;align-items:stretch;gap:8px}.pwt-dropdown{flex:1 1 0;min-width:0;height:44px;padding:0 36px 0 14px;background-color:var(--pwt-surface);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23ab03b6' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;border:1.5px solid var(--pwt-border);border-radius:var(--pwt-radius-md);color:var(--pwt-text);font-family:var(--pwt-font);font-size:14px;font-weight:600;outline:none;cursor:pointer;-moz-appearance:none;appearance:none;-webkit-appearance:none;transition:border-color var(--pwt-t) var(--pwt-ease),box-shadow var(--pwt-t) var(--pwt-ease)}.pwt-dropdown:hover:not(:disabled){border-color:var(--pwt-primary)}.pwt-dropdown:focus{border-color:var(--pwt-border-focus);box-shadow:0 0 0 3px var(--pwt-primary-glow)}.pwt-dropdown:disabled{cursor:not-allowed;opacity:.48}.pwt-button{height:44px;padding:0 20px;background:linear-gradient(135deg,var(--pwt-primary-lit) 0%,var(--pwt-primary) 55%,var(--pwt-primary-dim) 100%);border:none;border-radius:var(--pwt-radius-md);color:var(--pwt-primary-text);font-family:var(--pwt-font);font-size:14px;font-weight:700;letter-spacing:.015em;white-space:nowrap;cursor:pointer;box-shadow:0 2px 10px #ab03b661;transition:opacity var(--pwt-t) var(--pwt-ease),transform var(--pwt-t) var(--pwt-ease),box-shadow var(--pwt-t) var(--pwt-ease)}.pwt-button:hover:not(:disabled){opacity:.9;transform:translateY(-1px);box-shadow:0 4px 18px #ab03b680}.pwt-button:active:not(:disabled){transform:translateY(0);box-shadow:0 2px 8px #ab03b659}.pwt-button:focus-visible{outline:none;box-shadow:0 0 0 3px var(--pwt-primary-glow),0 2px 10px #ab03b661}.pwt-button:disabled{cursor:not-allowed;opacity:.4;transform:none;box-shadow:none}.pwt-status{display:flex;align-items:center;gap:7px;padding:8px 12px;font-size:12.5px;line-height:1.4;color:var(--pwt-muted);background:var(--pwt-surface);border:1px solid var(--pwt-border);border-radius:var(--pwt-radius-sm)}.pwt-status:before{content:"";display:block;flex-shrink:0;width:3px;height:28px;border-radius:var(--pwt-radius-pill);background:var(--pwt-primary);opacity:.5}.pwt-status--error{color:var(--pwt-error-text);background:var(--pwt-error-bg);border-color:var(--pwt-error-border)}.pwt-status--error:before{background:var(--pwt-error-border);opacity:1}.pwt-switch-network-btn{background:none;border:1.5px solid currentColor;border-radius:var(--pwt-radius-pill);padding:1px 10px;margin-left:2px;font-family:var(--pwt-font);font-size:inherit;font-weight:700;color:var(--pwt-error-text);cursor:pointer;vertical-align:middle;transition:background var(--pwt-t) var(--pwt-ease)}.pwt-switch-network-btn:hover:not(:disabled){background:var(--pwt-error-bg)}.pwt-switch-network-btn:disabled{cursor:not-allowed;opacity:.55}@keyframes pwt-shimmer{0%{opacity:1}50%{opacity:.45}to{opacity:1}}.pwt-dropdown[disabled]:not([data-no-shimmer]){animation:pwt-shimmer 1.4s var(--pwt-ease) infinite}.pwt-powered-by{margin-top:2px;align-self:flex-end;color:var(--pwt-muted);font-size:14px;text-decoration:none}.pwt-powered-by:hover{color:var(--pwt-text);text-decoration:none}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("react/jsx-runtime"),r=require("react"),v=require("ethers"),O="https://evm-api.deserialize.xyz",Z="https://evmrpc.0G.ai",Se="0G",L=16661,H="0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",Te="0x0000000000000000000000000000000000000000",ue=["function balanceOf(address owner) view returns (uint256)"],de={address:H,symbol:"OG",name:"0G",decimals:18,usdPrice:null};function G(e){const n=e.toLowerCase();return n===H.toLowerCase()||n===Te}function Q(e,n){for(const a of n){const s=e[a];if(typeof s=="string"&&s.trim())return s}return null}function X(e,n){for(const a of n){const s=e[a];if(typeof s=="number"&&Number.isFinite(s))return s;if(typeof s=="string"&&s.trim()){const l=Number(s);if(Number.isFinite(l))return l}}return null}function fe(e){if(!e||typeof e!="object")return null;const n=e,a=Q(n,["address","tokenAddress","token","contractAddress","token_address"]),s=Q(n,["symbol","tokenSymbol","ticker","token_symbol"]),l=Q(n,["name","tokenName","token_name","displayName"])??s,p=X(n,["decimals","tokenDecimals","tokenDecimal","token_decimals"]),w=X(n,["usdPrice","priceUsd","priceUSD","usd_price","tokenUsdPrice","tokenUSDPrice"]);return!a||!s||!l||p===null||!Number.isFinite(p)?null:{address:a,symbol:s,name:l,decimals:p,usdPrice:w!==null&&w>0?w:null}}function me(e){if(Array.isArray(e))return e;if(!e||typeof e!="object")return[];const n=e,a=["tokens","data","result","items","tokenList"];for(const s of a){const l=n[s];if(Array.isArray(l))return l;if(l!==null&&typeof l=="object")return[l]}return[n]}function Ne(e){return G(e)?H:e}function Ee(e){const n=[e.amountOut,e.toAmount,e.outAmount,e.amountBOut];for(const a of n)if(typeof a=="string"&&/^\d+$/.test(a))return BigInt(a);return 0n}function Ce(e){return Math.max(0,e)/100}function he(e,n,a){const s=Number(e);if(!Number.isFinite(s)||s<=0)throw new Error("Invalid USD amount");if(!Number.isFinite(n)||n<=0)throw new Error("Token USD price unavailable");const l=s/n,p=Math.min(18,Math.max(0,a));return v.parseUnits(l.toFixed(p),a)}async function R(e,n){const a=await fetch(e,n);if(!a.ok){const s=await a.text();throw new Error(`HTTP ${a.status} from ${e}: ${s}`)}return await a.json()}function xe(e){if(!e)return{};const n=e.match(/^#([0-9a-f]{6})$/i);if(!n)return{"--pwt-primary":e,"--pwt-border-focus":e};const a=parseInt(n[1].slice(0,2),16)/255,s=parseInt(n[1].slice(2,4),16)/255,l=parseInt(n[1].slice(4,6),16)/255,p=Math.max(a,s,l),w=Math.min(a,s,l);let T=0;const _=(p+w)/2,P=p-w,j=P===0?0:P/(_>.5?2-p-w:p+w);P!==0&&(p===a?T=((s-l)/P+(s<l?6:0))/6:p===s?T=((l-a)/P+2)/6:T=((a-s)/P+4)/6);const N=($,f,h)=>{const A=h<.5?h*(1+f):h+f-h*f,E=2*h-A,F=b=>(b<0&&(b+=1),b>1&&(b-=1),b<1/6?E+(A-E)*6*b:b<1/2?A:b<2/3?E+(A-E)*(2/3-b)*6:E),W=b=>Math.round(b*255).toString(16).padStart(2,"0");return`#${W(f===0?h:F($+1/3))}${W(f===0?h:F($))}${W(f===0?h:F($-1/3))}`},q=Math.round(a*255),y=Math.round(s*255),U=Math.round(l*255),d=$=>{const f=h=>Math.round(h*$).toString(16).padStart(2,"0");return`#${f(q)}${f(y)}${f(U)}`};return{"--pwt-primary":e,"--pwt-primary-dim":N(T,j,Math.max(0,_-.12)),"--pwt-primary-lit":N(T,j,Math.min(1,_+.1)),"--pwt-primary-glow":`rgba(${q}, ${y}, ${U}, 0.30)`,"--pwt-border-focus":e,"--pwt-bg":d(.15),"--pwt-surface":d(.24),"--pwt-border":d(.42),"--pwt-text":N(T,Math.min(j*.15,.12),.92),"--pwt-muted":N(T,Math.min(j*.15,.12),.62)}}function Y(e){if(!e||typeof e!="object")return!1;const n=e;return n.code===4001||n.code==="ACTION_REJECTED"||typeof n.message=="string"&&n.message.toLowerCase().includes("user rejected")}function Pe({provider:e,usdAmount:n,allowedTokens:a,slippageBps:s=100,partnerFees:l,onExecuteAction:p,onError:w,accentColor:T}){const _=r.useMemo(()=>new v.JsonRpcProvider(Z),[]),P=r.useRef(a);P.current=a;const j=a==="all"?"all":a.join(","),[N,q]=r.useState([]),[y,U]=r.useState(""),[d,$]=r.useState(""),[f,h]=r.useState(0n),[A,E]=r.useState(null),[F,W]=r.useState(null),[b,ee]=r.useState(!1),[te,ne]=r.useState(!1),[C,x]=r.useState(""),[D,se]=r.useState(!1),[ae,re]=r.useState(!1),i=r.useMemo(()=>N.find(t=>t.address.toLowerCase()===y.toLowerCase())??null,[N,y]),I=r.useMemo(()=>F??(i==null?void 0:i.usdPrice)??null,[F,i]),ie=r.useCallback(async()=>{const c=await(await e.getSigner()).getAddress();return $(c),c},[e]),we=r.useCallback(async()=>{re(!0);const t=`0x${L.toString(16)}`;try{await e.send("wallet_switchEthereumChain",[{chainId:t}])}catch(c){const o=c.code;if(o===4902||o===-32603)try{await e.send("wallet_addEthereumChain",[{chainId:t,chainName:"0G Newton",nativeCurrency:{name:"0G",symbol:"0G",decimals:18},rpcUrls:[Z]}])}catch(m){if(!Y(m))throw m}else if(!Y(c))throw c}finally{re(!1)}},[e]);r.useEffect(()=>{let t=!0;const c=async()=>{try{const u=await e.getNetwork();t&&se(Number(u.chainId)!==L)}catch{t&&se(!1)}};c();const o=window.ethereum,m=()=>{c()};return o==null||o.on("chainChanged",m),()=>{t=!1,o==null||o.removeListener("chainChanged",m)}},[e]),r.useEffect(()=>{if(!y){W(null);return}let t=!0;return R(`${O}/tokenPrice/${y}`).then(c=>{if(!t)return;const m=X(c,["result","price","usdPrice","priceUsd","priceUSD","usd_price"]);W(m!==null&&m>0?m:null)}).catch(()=>{t&&W(null)}),()=>{t=!1}},[y]);const oe=r.useCallback(async()=>{ee(!0);try{let t=[];const c=P.current;if(c==="all"){const u=await R(`${O}/tokenListWithDetails`),k=me(u);t=[de,...k.map(M=>fe(M)).filter(M=>M!==null)]}else{const u=c.filter(g=>G(g)),k=c.filter(g=>!G(g)),M=u.length>0?[de]:[],K=(await Promise.all(k.map(g=>R(`${O}/tokenDetails/${g}`)))).flatMap(g=>me(g));t=[...M,...K.map(g=>fe(g)).filter(g=>g!==null)]}const o=new Map;for(const u of t)o.set(u.address.toLowerCase(),u);const m=Array.from(o.values()).sort((u,k)=>u.symbol.localeCompare(k.symbol));q(m),U(u=>{var k;return u||((k=m[0])==null?void 0:k.address)||""})}finally{ee(!1)}},[]);r.useEffect(()=>{oe().catch(t=>{x("Failed to load token list. Please refresh and try again."),w==null||w(t)})},[oe,j,w]),r.useEffect(()=>{if(!C||C.startsWith("Getting")||C.startsWith("Awaiting")||C.startsWith("Sending")||C.startsWith("Waiting")||C.startsWith("Completing"))return;const t=setTimeout(()=>x(""),3e3);return()=>clearTimeout(t)},[C]),r.useEffect(()=>{ie().catch(()=>{$("")})},[ie]),r.useEffect(()=>{let t=!0;return(async()=>{if(!y||!d){h(0n);return}try{if(G(y)){const u=await e.getBalance(d);t&&h(u);return}const m=await new v.Contract(y,ue,e).balanceOf(d);t&&h(m)}catch{try{if(G(y)){const o=await _.getBalance(d);t&&h(o)}else{const m=await new v.Contract(y,ue,_).balanceOf(d);t&&h(m)}}catch{t&&h(0n)}}})().catch(()=>{t&&h(0n)}),()=>{t=!1}},[_,e,y,d,D]);const ye=te||D||!d||b||N.length===0||!y;r.useEffect(()=>{let t=!0;return(async()=>{if(!i||!d){E(null);return}try{if(!I)throw new Error("USD price unavailable");const o=he(n,I,i.decimals);t&&E(o)}catch{t&&E(null)}})().catch(()=>{t&&E(null)}),()=>{t=!1}},[n,i,d,I]);const pe=A!==null?f<A:f<=0n,J=ye||!!i&&!!d&&A===null||pe,ce=r.useMemo(()=>{if(!i||!d)return"";const t=Number.isFinite(i.decimals)?i.decimals:18,c=v.formatUnits(f,t),[o,m=""]=c.split("."),u=m.slice(0,6).replace(/0+$/,"");return`${o}${u?`.${u}`:""} ${i.symbol}`},[f,i,d]),le=r.useMemo(()=>{if(!i||!d||!I)return"";const t=Number.isFinite(i.decimals)?i.decimals:18,o=Number(v.formatUnits(f,t))*I;return Number.isFinite(o)?`$${o.toFixed(2)}`:""},[f,i,I,d]),be=r.useCallback(async()=>{if(!(J||!i)){ne(!0);try{const t=await e.getNetwork();if(Number(t.chainId)!==L)throw new Error(`Wrong network. Please switch your wallet to the 0G network (chain ID ${L}).`);const c=await e.getSigner(),o=d||await c.getAddress(),m=Ne(i.address);if(!I)throw new Error(`Price data unavailable for ${i.symbol}. Please try again shortly.`);const u=he(n,I,i.decimals);if(f<u){const B=v.formatUnits(u,i.decimals),z=v.formatUnits(f,i.decimals);throw new Error(`Insufficient ${i.symbol} balance. Need ${B}, have ${z}.`)}x("Getting quote…");const k=await R(`${O}/quote`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tokenA:m,tokenB:H,dexId:"ALL",amountIn:u.toString()})});if(Ee(k)<=0n)throw new Error(`No swap route found for ${i.symbol}. Try selecting a different token.`);x("Awaiting wallet confirmation…");const V={publicKey:o,quote:k,slippage:Ce(s)};l&&(V.partnerFees=l);const K=await R(`${O}/swap`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(V)}),g=Array.isArray(K.transactions)?K.transactions:[];if(g.length===0)throw new Error("Swap service returned an unexpected response. Please try again.");x("Sending transaction…");const ke=[];for(const B of g){const z=await c.sendTransaction({to:B.to,data:B.data,value:B.value?BigInt(B.value):0n});ke.push(z.hash),x("Waiting for confirmation…"),await z.wait(1)}x("Completing purchase…"),await p(),x("Success")}catch(t){if(Y(t))x("Transaction cancelled.");else{const c=t instanceof Error?t.message:"Payment failed. Please try again.";x(`Error: ${c}`)}w==null||w(t)}finally{ne(!1)}}},[w,p,l,J,e,n,f,i,I,s,d]),ge=r.useMemo(()=>xe(T),[T]);return S.jsxs("div",{className:"pwt-root",style:ge,children:[S.jsx("label",{className:"pwt-label",htmlFor:"pwt-token-select",children:"Pay with"}),S.jsxs("div",{className:"pwt-row",children:[S.jsx("select",{id:"pwt-token-select",className:"pwt-dropdown",value:y,onChange:t=>U(t.target.value),disabled:te||b||N.length===0,"data-no-shimmer":!b||void 0,children:N.map(t=>S.jsx("option",{value:t.address,children:t.symbol},t.address))}),S.jsxs("button",{type:"button",className:"pwt-button",onClick:be,disabled:J,children:["Pay $",n]})]}),D?S.jsxs("div",{className:"pwt-status pwt-status--error",children:["Wrong network —"," ",S.jsx("button",{type:"button",className:"pwt-switch-network-btn",onClick:we,disabled:ae,children:ae?"Switching…":"Switch to 0G"})]}):null,!D&&C?S.jsx("div",{className:"pwt-status",children:C}):null,!D&&!C&&ce?S.jsxs("div",{className:"pwt-status",children:["Balance: ",ce,le?` (${le})`:""]}):null,S.jsx("a",{className:"pwt-powered-by",href:"https://x.com/Deserialize_",target:"_blank",rel:"noreferrer noopener",children:"Powered by Deserialize"})]})}const Ie={API_BASE_URL:O,FALLBACK_RPC:Z,NETWORK_ID:Se,REQUIRED_CHAIN_ID:L,NATIVE_SENTINEL:H};exports.PAY_WITH_TOKEN_WIDGET_CONSTANTS=Ie;exports.PayWithTokenWidget=Pe;
|
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
import { jsxs as j, jsx as O } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo as U, useRef as Ie, useState as k, useCallback as Q, useEffect as _ } from "react";
|
|
3
|
+
import { JsonRpcProvider as Pe, formatUnits as Y, Contract as he, parseUnits as Ae } from "ethers";
|
|
4
|
+
const M = "https://evm-api.deserialize.xyz", ne = "https://evmrpc.0G.ai", Ee = "0G", H = 16661, K = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", xe = "0x0000000000000000000000000000000000000000", we = [
|
|
5
|
+
"function balanceOf(address owner) view returns (uint256)"
|
|
6
|
+
], pe = {
|
|
7
|
+
address: K,
|
|
8
|
+
symbol: "OG",
|
|
9
|
+
name: "0G",
|
|
10
|
+
decimals: 18,
|
|
11
|
+
usdPrice: null
|
|
12
|
+
};
|
|
13
|
+
function z(e) {
|
|
14
|
+
const n = e.toLowerCase();
|
|
15
|
+
return n === K.toLowerCase() || n === xe;
|
|
16
|
+
}
|
|
17
|
+
function ee(e, n) {
|
|
18
|
+
for (const a of n) {
|
|
19
|
+
const s = e[a];
|
|
20
|
+
if (typeof s == "string" && s.trim())
|
|
21
|
+
return s;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
function se(e, n) {
|
|
26
|
+
for (const a of n) {
|
|
27
|
+
const s = e[a];
|
|
28
|
+
if (typeof s == "number" && Number.isFinite(s))
|
|
29
|
+
return s;
|
|
30
|
+
if (typeof s == "string" && s.trim()) {
|
|
31
|
+
const c = Number(s);
|
|
32
|
+
if (Number.isFinite(c))
|
|
33
|
+
return c;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function ye(e) {
|
|
39
|
+
if (!e || typeof e != "object")
|
|
40
|
+
return null;
|
|
41
|
+
const n = e, a = ee(n, [
|
|
42
|
+
"address",
|
|
43
|
+
"tokenAddress",
|
|
44
|
+
"token",
|
|
45
|
+
"contractAddress",
|
|
46
|
+
"token_address"
|
|
47
|
+
]), s = ee(n, [
|
|
48
|
+
"symbol",
|
|
49
|
+
"tokenSymbol",
|
|
50
|
+
"ticker",
|
|
51
|
+
"token_symbol"
|
|
52
|
+
]), c = ee(n, [
|
|
53
|
+
"name",
|
|
54
|
+
"tokenName",
|
|
55
|
+
"token_name",
|
|
56
|
+
"displayName"
|
|
57
|
+
]) ?? s, p = se(n, [
|
|
58
|
+
"decimals",
|
|
59
|
+
"tokenDecimals",
|
|
60
|
+
"tokenDecimal",
|
|
61
|
+
"token_decimals"
|
|
62
|
+
]), h = se(n, [
|
|
63
|
+
"usdPrice",
|
|
64
|
+
"priceUsd",
|
|
65
|
+
"priceUSD",
|
|
66
|
+
"usd_price",
|
|
67
|
+
"tokenUsdPrice",
|
|
68
|
+
"tokenUSDPrice"
|
|
69
|
+
]);
|
|
70
|
+
return !a || !s || !c || p === null || !Number.isFinite(p) ? null : {
|
|
71
|
+
address: a,
|
|
72
|
+
symbol: s,
|
|
73
|
+
name: c,
|
|
74
|
+
decimals: p,
|
|
75
|
+
usdPrice: h !== null && h > 0 ? h : null
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function ge(e) {
|
|
79
|
+
if (Array.isArray(e))
|
|
80
|
+
return e;
|
|
81
|
+
if (!e || typeof e != "object")
|
|
82
|
+
return [];
|
|
83
|
+
const n = e, a = ["tokens", "data", "result", "items", "tokenList"];
|
|
84
|
+
for (const s of a) {
|
|
85
|
+
const c = n[s];
|
|
86
|
+
if (Array.isArray(c))
|
|
87
|
+
return c;
|
|
88
|
+
if (c !== null && typeof c == "object")
|
|
89
|
+
return [c];
|
|
90
|
+
}
|
|
91
|
+
return [n];
|
|
92
|
+
}
|
|
93
|
+
function ve(e) {
|
|
94
|
+
return z(e) ? K : e;
|
|
95
|
+
}
|
|
96
|
+
function _e(e) {
|
|
97
|
+
const n = [
|
|
98
|
+
e.amountOut,
|
|
99
|
+
e.toAmount,
|
|
100
|
+
e.outAmount,
|
|
101
|
+
e.amountBOut
|
|
102
|
+
];
|
|
103
|
+
for (const a of n)
|
|
104
|
+
if (typeof a == "string" && /^\d+$/.test(a))
|
|
105
|
+
return BigInt(a);
|
|
106
|
+
return 0n;
|
|
107
|
+
}
|
|
108
|
+
function Fe(e) {
|
|
109
|
+
return Math.max(0, e) / 100;
|
|
110
|
+
}
|
|
111
|
+
function be(e, n, a) {
|
|
112
|
+
const s = Number(e);
|
|
113
|
+
if (!Number.isFinite(s) || s <= 0)
|
|
114
|
+
throw new Error("Invalid USD amount");
|
|
115
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
116
|
+
throw new Error("Token USD price unavailable");
|
|
117
|
+
const c = s / n, p = Math.min(18, Math.max(0, a));
|
|
118
|
+
return Ae(c.toFixed(p), a);
|
|
119
|
+
}
|
|
120
|
+
async function G(e, n) {
|
|
121
|
+
const a = await fetch(e, n);
|
|
122
|
+
if (!a.ok) {
|
|
123
|
+
const s = await a.text();
|
|
124
|
+
throw new Error(`HTTP ${a.status} from ${e}: ${s}`);
|
|
125
|
+
}
|
|
126
|
+
return await a.json();
|
|
127
|
+
}
|
|
128
|
+
function Be(e) {
|
|
129
|
+
if (!e) return {};
|
|
130
|
+
const n = e.match(/^#([0-9a-f]{6})$/i);
|
|
131
|
+
if (!n)
|
|
132
|
+
return {
|
|
133
|
+
"--pwt-primary": e,
|
|
134
|
+
"--pwt-border-focus": e
|
|
135
|
+
};
|
|
136
|
+
const a = parseInt(n[1].slice(0, 2), 16) / 255, s = parseInt(n[1].slice(2, 4), 16) / 255, c = parseInt(n[1].slice(4, 6), 16) / 255, p = Math.max(a, s, c), h = Math.min(a, s, c);
|
|
137
|
+
let T = 0;
|
|
138
|
+
const x = (p + h) / 2, I = p - h, F = I === 0 ? 0 : I / (x > 0.5 ? 2 - p - h : p + h);
|
|
139
|
+
I !== 0 && (p === a ? T = ((s - c) / I + (s < c ? 6 : 0)) / 6 : p === s ? T = ((c - a) / I + 2) / 6 : T = ((a - s) / I + 4) / 6);
|
|
140
|
+
const N = (A, u, m) => {
|
|
141
|
+
const E = m < 0.5 ? m * (1 + u) : m + u - m * u, S = 2 * m - E, B = (y) => (y < 0 && (y += 1), y > 1 && (y -= 1), y < 1 / 6 ? S + (E - S) * 6 * y : y < 1 / 2 ? E : y < 2 / 3 ? S + (E - S) * (2 / 3 - y) * 6 : S), v = (y) => Math.round(y * 255).toString(16).padStart(2, "0");
|
|
142
|
+
return `#${v(u === 0 ? m : B(A + 1 / 3))}${v(u === 0 ? m : B(A))}${v(u === 0 ? m : B(A - 1 / 3))}`;
|
|
143
|
+
}, J = Math.round(a * 255), w = Math.round(s * 255), L = Math.round(c * 255), d = (A) => {
|
|
144
|
+
const u = (m) => Math.round(m * A).toString(16).padStart(2, "0");
|
|
145
|
+
return `#${u(J)}${u(w)}${u(L)}`;
|
|
146
|
+
};
|
|
147
|
+
return {
|
|
148
|
+
// Accent shades (HSL — hue/saturation preserved)
|
|
149
|
+
"--pwt-primary": e,
|
|
150
|
+
"--pwt-primary-dim": N(T, F, Math.max(0, x - 0.12)),
|
|
151
|
+
"--pwt-primary-lit": N(T, F, Math.min(1, x + 0.1)),
|
|
152
|
+
"--pwt-primary-glow": `rgba(${J}, ${w}, ${L}, 0.30)`,
|
|
153
|
+
"--pwt-border-focus": e,
|
|
154
|
+
// Dark surfaces — accent hue mixed into black so the card pops
|
|
155
|
+
"--pwt-bg": d(0.15),
|
|
156
|
+
"--pwt-surface": d(0.24),
|
|
157
|
+
"--pwt-border": d(0.42),
|
|
158
|
+
// Light text for dark backgrounds
|
|
159
|
+
"--pwt-text": N(T, Math.min(F * 0.15, 0.12), 0.92),
|
|
160
|
+
"--pwt-muted": N(T, Math.min(F * 0.15, 0.12), 0.62)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function te(e) {
|
|
164
|
+
if (!e || typeof e != "object") return !1;
|
|
165
|
+
const n = e;
|
|
166
|
+
return n.code === 4001 || n.code === "ACTION_REJECTED" || typeof n.message == "string" && n.message.toLowerCase().includes("user rejected");
|
|
167
|
+
}
|
|
168
|
+
function Me({
|
|
169
|
+
provider: e,
|
|
170
|
+
usdAmount: n,
|
|
171
|
+
allowedTokens: a,
|
|
172
|
+
slippageBps: s = 100,
|
|
173
|
+
partnerFees: c,
|
|
174
|
+
onExecuteAction: p,
|
|
175
|
+
onError: h,
|
|
176
|
+
accentColor: T
|
|
177
|
+
}) {
|
|
178
|
+
const x = U(() => new Pe(ne), []), I = Ie(a);
|
|
179
|
+
I.current = a;
|
|
180
|
+
const F = a === "all" ? "all" : a.join(","), [N, J] = k([]), [w, L] = k(""), [d, A] = k(""), [u, m] = k(0n), [E, S] = k(null), [B, v] = k(null), [y, ae] = k(!1), [re, ie] = k(!1), [$, C] = k(""), [R, oe] = k(!1), [ce, le] = k(!1), r = U(
|
|
181
|
+
() => N.find(
|
|
182
|
+
(t) => t.address.toLowerCase() === w.toLowerCase()
|
|
183
|
+
) ?? null,
|
|
184
|
+
[N, w]
|
|
185
|
+
), P = U(
|
|
186
|
+
() => B ?? (r == null ? void 0 : r.usdPrice) ?? null,
|
|
187
|
+
[B, r]
|
|
188
|
+
), de = Q(async () => {
|
|
189
|
+
const o = await (await e.getSigner()).getAddress();
|
|
190
|
+
return A(o), o;
|
|
191
|
+
}, [e]), ke = Q(async () => {
|
|
192
|
+
le(!0);
|
|
193
|
+
const t = `0x${H.toString(16)}`;
|
|
194
|
+
try {
|
|
195
|
+
await e.send("wallet_switchEthereumChain", [
|
|
196
|
+
{ chainId: t }
|
|
197
|
+
]);
|
|
198
|
+
} catch (o) {
|
|
199
|
+
const i = o.code;
|
|
200
|
+
if (i === 4902 || i === -32603)
|
|
201
|
+
try {
|
|
202
|
+
await e.send("wallet_addEthereumChain", [
|
|
203
|
+
{
|
|
204
|
+
chainId: t,
|
|
205
|
+
chainName: "0G Newton",
|
|
206
|
+
nativeCurrency: { name: "0G", symbol: "0G", decimals: 18 },
|
|
207
|
+
rpcUrls: [ne]
|
|
208
|
+
}
|
|
209
|
+
]);
|
|
210
|
+
} catch (f) {
|
|
211
|
+
if (!te(f)) throw f;
|
|
212
|
+
}
|
|
213
|
+
else if (!te(o))
|
|
214
|
+
throw o;
|
|
215
|
+
} finally {
|
|
216
|
+
le(!1);
|
|
217
|
+
}
|
|
218
|
+
}, [e]);
|
|
219
|
+
_(() => {
|
|
220
|
+
let t = !0;
|
|
221
|
+
const o = async () => {
|
|
222
|
+
try {
|
|
223
|
+
const l = await e.getNetwork();
|
|
224
|
+
t && oe(Number(l.chainId) !== H);
|
|
225
|
+
} catch {
|
|
226
|
+
t && oe(!1);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
o();
|
|
230
|
+
const i = window.ethereum, f = () => {
|
|
231
|
+
o();
|
|
232
|
+
};
|
|
233
|
+
return i == null || i.on("chainChanged", f), () => {
|
|
234
|
+
t = !1, i == null || i.removeListener("chainChanged", f);
|
|
235
|
+
};
|
|
236
|
+
}, [e]), _(() => {
|
|
237
|
+
if (!w) {
|
|
238
|
+
v(null);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
let t = !0;
|
|
242
|
+
return G(`${M}/tokenPrice/${w}`).then((o) => {
|
|
243
|
+
if (!t) return;
|
|
244
|
+
const f = se(o, [
|
|
245
|
+
"result",
|
|
246
|
+
"price",
|
|
247
|
+
"usdPrice",
|
|
248
|
+
"priceUsd",
|
|
249
|
+
"priceUSD",
|
|
250
|
+
"usd_price"
|
|
251
|
+
]);
|
|
252
|
+
v(f !== null && f > 0 ? f : null);
|
|
253
|
+
}).catch(() => {
|
|
254
|
+
t && v(null);
|
|
255
|
+
}), () => {
|
|
256
|
+
t = !1;
|
|
257
|
+
};
|
|
258
|
+
}, [w]);
|
|
259
|
+
const ue = Q(async () => {
|
|
260
|
+
ae(!0);
|
|
261
|
+
try {
|
|
262
|
+
let t = [];
|
|
263
|
+
const o = I.current;
|
|
264
|
+
if (o === "all") {
|
|
265
|
+
const l = await G(
|
|
266
|
+
`${M}/tokenListWithDetails`
|
|
267
|
+
), b = ge(l);
|
|
268
|
+
t = [
|
|
269
|
+
pe,
|
|
270
|
+
...b.map((W) => ye(W)).filter((W) => W !== null)
|
|
271
|
+
];
|
|
272
|
+
} else {
|
|
273
|
+
const l = o.filter((g) => z(g)), b = o.filter((g) => !z(g)), W = l.length > 0 ? [pe] : [], q = (await Promise.all(
|
|
274
|
+
b.map(
|
|
275
|
+
(g) => G(`${M}/tokenDetails/${g}`)
|
|
276
|
+
)
|
|
277
|
+
)).flatMap(
|
|
278
|
+
(g) => ge(g)
|
|
279
|
+
);
|
|
280
|
+
t = [
|
|
281
|
+
...W,
|
|
282
|
+
...q.map((g) => ye(g)).filter((g) => g !== null)
|
|
283
|
+
];
|
|
284
|
+
}
|
|
285
|
+
const i = /* @__PURE__ */ new Map();
|
|
286
|
+
for (const l of t)
|
|
287
|
+
i.set(l.address.toLowerCase(), l);
|
|
288
|
+
const f = Array.from(i.values()).sort(
|
|
289
|
+
(l, b) => l.symbol.localeCompare(b.symbol)
|
|
290
|
+
);
|
|
291
|
+
J(f), L((l) => {
|
|
292
|
+
var b;
|
|
293
|
+
return l || ((b = f[0]) == null ? void 0 : b.address) || "";
|
|
294
|
+
});
|
|
295
|
+
} finally {
|
|
296
|
+
ae(!1);
|
|
297
|
+
}
|
|
298
|
+
}, []);
|
|
299
|
+
_(() => {
|
|
300
|
+
ue().catch((t) => {
|
|
301
|
+
C("Failed to load token list. Please refresh and try again."), h == null || h(t);
|
|
302
|
+
});
|
|
303
|
+
}, [ue, F, h]), _(() => {
|
|
304
|
+
if (!$ || $.startsWith("Getting") || $.startsWith("Awaiting") || $.startsWith("Sending") || $.startsWith("Waiting") || $.startsWith("Completing"))
|
|
305
|
+
return;
|
|
306
|
+
const t = setTimeout(() => C(""), 3e3);
|
|
307
|
+
return () => clearTimeout(t);
|
|
308
|
+
}, [$]), _(() => {
|
|
309
|
+
de().catch(() => {
|
|
310
|
+
A("");
|
|
311
|
+
});
|
|
312
|
+
}, [de]), _(() => {
|
|
313
|
+
let t = !0;
|
|
314
|
+
return (async () => {
|
|
315
|
+
if (!w || !d) {
|
|
316
|
+
m(0n);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
try {
|
|
320
|
+
if (z(w)) {
|
|
321
|
+
const l = await e.getBalance(d);
|
|
322
|
+
t && m(l);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const f = await new he(
|
|
326
|
+
w,
|
|
327
|
+
we,
|
|
328
|
+
e
|
|
329
|
+
).balanceOf(
|
|
330
|
+
d
|
|
331
|
+
);
|
|
332
|
+
t && m(f);
|
|
333
|
+
} catch {
|
|
334
|
+
try {
|
|
335
|
+
if (z(w)) {
|
|
336
|
+
const i = await x.getBalance(d);
|
|
337
|
+
t && m(i);
|
|
338
|
+
} else {
|
|
339
|
+
const f = await new he(
|
|
340
|
+
w,
|
|
341
|
+
we,
|
|
342
|
+
x
|
|
343
|
+
).balanceOf(
|
|
344
|
+
d
|
|
345
|
+
);
|
|
346
|
+
t && m(f);
|
|
347
|
+
}
|
|
348
|
+
} catch {
|
|
349
|
+
t && m(0n);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
})().catch(() => {
|
|
353
|
+
t && m(0n);
|
|
354
|
+
}), () => {
|
|
355
|
+
t = !1;
|
|
356
|
+
};
|
|
357
|
+
}, [x, e, w, d, R]);
|
|
358
|
+
const Te = re || R || !d || y || N.length === 0 || !w;
|
|
359
|
+
_(() => {
|
|
360
|
+
let t = !0;
|
|
361
|
+
return (async () => {
|
|
362
|
+
if (!r || !d) {
|
|
363
|
+
S(null);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
try {
|
|
367
|
+
if (!P)
|
|
368
|
+
throw new Error("USD price unavailable");
|
|
369
|
+
const i = be(
|
|
370
|
+
n,
|
|
371
|
+
P,
|
|
372
|
+
r.decimals
|
|
373
|
+
);
|
|
374
|
+
t && S(i);
|
|
375
|
+
} catch {
|
|
376
|
+
t && S(null);
|
|
377
|
+
}
|
|
378
|
+
})().catch(() => {
|
|
379
|
+
t && S(null);
|
|
380
|
+
}), () => {
|
|
381
|
+
t = !1;
|
|
382
|
+
};
|
|
383
|
+
}, [n, r, d, P]);
|
|
384
|
+
const Ne = E !== null ? u < E : u <= 0n, Z = Te || !!r && !!d && E === null || Ne, fe = U(() => {
|
|
385
|
+
if (!r || !d) return "";
|
|
386
|
+
const t = Number.isFinite(r.decimals) ? r.decimals : 18, o = Y(u, t), [i, f = ""] = o.split("."), l = f.slice(0, 6).replace(/0+$/, "");
|
|
387
|
+
return `${i}${l ? `.${l}` : ""} ${r.symbol}`;
|
|
388
|
+
}, [u, r, d]), me = U(() => {
|
|
389
|
+
if (!r || !d || !P) return "";
|
|
390
|
+
const t = Number.isFinite(r.decimals) ? r.decimals : 18, i = Number(Y(u, t)) * P;
|
|
391
|
+
return Number.isFinite(i) ? `$${i.toFixed(2)}` : "";
|
|
392
|
+
}, [u, r, P, d]), Se = Q(async () => {
|
|
393
|
+
if (!(Z || !r)) {
|
|
394
|
+
ie(!0);
|
|
395
|
+
try {
|
|
396
|
+
const t = await e.getNetwork();
|
|
397
|
+
if (Number(t.chainId) !== H)
|
|
398
|
+
throw new Error(
|
|
399
|
+
`Wrong network. Please switch your wallet to the 0G network (chain ID ${H}).`
|
|
400
|
+
);
|
|
401
|
+
const o = await e.getSigner(), i = d || await o.getAddress(), f = ve(r.address);
|
|
402
|
+
if (!P)
|
|
403
|
+
throw new Error(
|
|
404
|
+
`Price data unavailable for ${r.symbol}. Please try again shortly.`
|
|
405
|
+
);
|
|
406
|
+
const l = be(
|
|
407
|
+
n,
|
|
408
|
+
P,
|
|
409
|
+
r.decimals
|
|
410
|
+
);
|
|
411
|
+
if (u < l) {
|
|
412
|
+
const D = Y(l, r.decimals), V = Y(
|
|
413
|
+
u,
|
|
414
|
+
r.decimals
|
|
415
|
+
);
|
|
416
|
+
throw new Error(
|
|
417
|
+
`Insufficient ${r.symbol} balance. Need ${D}, have ${V}.`
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
C("Getting quote…");
|
|
421
|
+
const b = await G(`${M}/quote`, {
|
|
422
|
+
method: "POST",
|
|
423
|
+
headers: { "Content-Type": "application/json" },
|
|
424
|
+
body: JSON.stringify({
|
|
425
|
+
tokenA: f,
|
|
426
|
+
tokenB: K,
|
|
427
|
+
dexId: "ALL",
|
|
428
|
+
amountIn: l.toString()
|
|
429
|
+
})
|
|
430
|
+
});
|
|
431
|
+
if (_e(b) <= 0n)
|
|
432
|
+
throw new Error(
|
|
433
|
+
`No swap route found for ${r.symbol}. Try selecting a different token.`
|
|
434
|
+
);
|
|
435
|
+
C("Awaiting wallet confirmation…");
|
|
436
|
+
const X = {
|
|
437
|
+
publicKey: i,
|
|
438
|
+
quote: b,
|
|
439
|
+
slippage: Fe(s)
|
|
440
|
+
};
|
|
441
|
+
c && (X.partnerFees = c);
|
|
442
|
+
const q = await G(
|
|
443
|
+
`${M}/swap`,
|
|
444
|
+
{
|
|
445
|
+
method: "POST",
|
|
446
|
+
headers: { "Content-Type": "application/json" },
|
|
447
|
+
body: JSON.stringify(X)
|
|
448
|
+
}
|
|
449
|
+
), g = Array.isArray(q.transactions) ? q.transactions : [];
|
|
450
|
+
if (g.length === 0)
|
|
451
|
+
throw new Error(
|
|
452
|
+
"Swap service returned an unexpected response. Please try again."
|
|
453
|
+
);
|
|
454
|
+
C("Sending transaction…");
|
|
455
|
+
const Ce = [];
|
|
456
|
+
for (const D of g) {
|
|
457
|
+
const V = await o.sendTransaction({
|
|
458
|
+
to: D.to,
|
|
459
|
+
data: D.data,
|
|
460
|
+
value: D.value ? BigInt(D.value) : 0n
|
|
461
|
+
});
|
|
462
|
+
Ce.push(V.hash), C("Waiting for confirmation…"), await V.wait(1);
|
|
463
|
+
}
|
|
464
|
+
C("Completing purchase…"), await p(), C("Success");
|
|
465
|
+
} catch (t) {
|
|
466
|
+
if (te(t))
|
|
467
|
+
C("Transaction cancelled.");
|
|
468
|
+
else {
|
|
469
|
+
const o = t instanceof Error ? t.message : "Payment failed. Please try again.";
|
|
470
|
+
C(`Error: ${o}`);
|
|
471
|
+
}
|
|
472
|
+
h == null || h(t);
|
|
473
|
+
} finally {
|
|
474
|
+
ie(!1);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}, [
|
|
478
|
+
h,
|
|
479
|
+
p,
|
|
480
|
+
c,
|
|
481
|
+
Z,
|
|
482
|
+
e,
|
|
483
|
+
n,
|
|
484
|
+
u,
|
|
485
|
+
r,
|
|
486
|
+
P,
|
|
487
|
+
s,
|
|
488
|
+
d
|
|
489
|
+
]), $e = U(
|
|
490
|
+
() => Be(T),
|
|
491
|
+
[T]
|
|
492
|
+
);
|
|
493
|
+
return /* @__PURE__ */ j("div", { className: "pwt-root", style: $e, children: [
|
|
494
|
+
/* @__PURE__ */ O("label", { className: "pwt-label", htmlFor: "pwt-token-select", children: "Pay with" }),
|
|
495
|
+
/* @__PURE__ */ j("div", { className: "pwt-row", children: [
|
|
496
|
+
/* @__PURE__ */ O(
|
|
497
|
+
"select",
|
|
498
|
+
{
|
|
499
|
+
id: "pwt-token-select",
|
|
500
|
+
className: "pwt-dropdown",
|
|
501
|
+
value: w,
|
|
502
|
+
onChange: (t) => L(t.target.value),
|
|
503
|
+
disabled: re || y || N.length === 0,
|
|
504
|
+
"data-no-shimmer": !y || void 0,
|
|
505
|
+
children: N.map((t) => /* @__PURE__ */ O("option", { value: t.address, children: t.symbol }, t.address))
|
|
506
|
+
}
|
|
507
|
+
),
|
|
508
|
+
/* @__PURE__ */ j(
|
|
509
|
+
"button",
|
|
510
|
+
{
|
|
511
|
+
type: "button",
|
|
512
|
+
className: "pwt-button",
|
|
513
|
+
onClick: Se,
|
|
514
|
+
disabled: Z,
|
|
515
|
+
children: [
|
|
516
|
+
"Pay $",
|
|
517
|
+
n
|
|
518
|
+
]
|
|
519
|
+
}
|
|
520
|
+
)
|
|
521
|
+
] }),
|
|
522
|
+
R ? /* @__PURE__ */ j("div", { className: "pwt-status pwt-status--error", children: [
|
|
523
|
+
"Wrong network —",
|
|
524
|
+
" ",
|
|
525
|
+
/* @__PURE__ */ O(
|
|
526
|
+
"button",
|
|
527
|
+
{
|
|
528
|
+
type: "button",
|
|
529
|
+
className: "pwt-switch-network-btn",
|
|
530
|
+
onClick: ke,
|
|
531
|
+
disabled: ce,
|
|
532
|
+
children: ce ? "Switching…" : "Switch to 0G"
|
|
533
|
+
}
|
|
534
|
+
)
|
|
535
|
+
] }) : null,
|
|
536
|
+
!R && $ ? /* @__PURE__ */ O("div", { className: "pwt-status", children: $ }) : null,
|
|
537
|
+
!R && !$ && fe ? /* @__PURE__ */ j("div", { className: "pwt-status", children: [
|
|
538
|
+
"Balance: ",
|
|
539
|
+
fe,
|
|
540
|
+
me ? ` (${me})` : ""
|
|
541
|
+
] }) : null,
|
|
542
|
+
/* @__PURE__ */ O(
|
|
543
|
+
"a",
|
|
544
|
+
{
|
|
545
|
+
className: "pwt-powered-by",
|
|
546
|
+
href: "https://x.com/Deserialize_",
|
|
547
|
+
target: "_blank",
|
|
548
|
+
rel: "noreferrer noopener",
|
|
549
|
+
children: "Powered by Deserialize"
|
|
550
|
+
}
|
|
551
|
+
)
|
|
552
|
+
] });
|
|
553
|
+
}
|
|
554
|
+
const Le = {
|
|
555
|
+
API_BASE_URL: M,
|
|
556
|
+
FALLBACK_RPC: ne,
|
|
557
|
+
NETWORK_ID: Ee,
|
|
558
|
+
REQUIRED_CHAIN_ID: H,
|
|
559
|
+
NATIVE_SENTINEL: K
|
|
560
|
+
};
|
|
561
|
+
export {
|
|
562
|
+
Le as PAY_WITH_TOKEN_WIDGET_CONSTANTS,
|
|
563
|
+
Me as PayWithTokenWidget
|
|
564
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "deserialize-deposit-widget",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Deserialize Deposit widget that allows dapps accept any token from the user and consolidate's it into the preferred token of the dapp.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/swap-widget.cjs",
|
|
8
|
+
"module": "./dist/swap-widget.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/swap-widget.js",
|
|
14
|
+
"require": "./dist/swap-widget.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./style.css": "./dist/style.css"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"sideEffects": [
|
|
22
|
+
"**/*.css"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"dev": "vite",
|
|
26
|
+
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
27
|
+
"build": "npm run clean && vite build && tsc -p tsconfig.build.json",
|
|
28
|
+
"prepublishOnly": "npm run build",
|
|
29
|
+
"preview": "vite preview",
|
|
30
|
+
"typecheck": "tsc --noEmit"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
34
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"ethers": "^6.15.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^22.8.6",
|
|
41
|
+
"@types/react": "^18.3.12",
|
|
42
|
+
"@types/react-dom": "^18.3.1",
|
|
43
|
+
"@vitejs/plugin-react": "^4.3.2",
|
|
44
|
+
"react": "^18.3.1",
|
|
45
|
+
"react-dom": "^18.3.1",
|
|
46
|
+
"typescript": "^5.6.3",
|
|
47
|
+
"vite": "^5.4.10"
|
|
48
|
+
}
|
|
49
|
+
}
|