@idosgames/wallet 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 iDos Games
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,254 @@
1
+ # @idosgames/wallet
2
+
3
+ The on-chain half of the iDosGames blockchain flow. `@idosgames/core`'s
4
+ `client.blockchain` is deliberately **report-only**: it verifies deposits and
5
+ issues signed withdrawals but never signs or broadcasts a transaction. This
6
+ package is the missing piece — it **connects browser & mobile wallets** and
7
+ runs the exact RewardPool contract calls, threading them through the
8
+ `request → submit → confirm` / `approve → deposit → report` lifecycle so a
9
+ player can move tokens and NFTs in and out of the game.
10
+
11
+ - **EVM** — [wagmi](https://wagmi.sh) + [viem](https://viem.sh) +
12
+ WalletConnect. Browser (MetaMask / any injected wallet) and mobile (via
13
+ WalletConnect) are both first-class.
14
+ - **Solana** — `@solana/wallet-adapter` for connection; the on-chain
15
+ instruction building is delegated to a small `SolanaProgramAdapter` you
16
+ implement with your program's IDL (see [Solana](#solana)).
17
+
18
+ Everything stays **server-authoritative**: the bridge only submits what the
19
+ backend signed/verified and mirrors the confirmed result into the core cache.
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ npm i @idosgames/wallet @idosgames/core
25
+ # EVM peer deps:
26
+ npm i wagmi viem @tanstack/react-query
27
+ # Solana peer deps (only if you support Solana networks):
28
+ npm i @solana/web3.js @solana/wallet-adapter-react @solana/wallet-adapter-base @solana/wallet-adapter-wallets
29
+ ```
30
+
31
+ Two entry points:
32
+
33
+ - `@idosgames/wallet` — framework-agnostic bridge functions (viem +
34
+ `@solana/web3.js` only). Use these directly if you're not on React.
35
+ - `@idosgames/wallet/react` — wagmi/React hooks + providers. Everything below
36
+ uses these.
37
+
38
+ ## Operation category
39
+
40
+ The updated RewardPool contract tags each operation with a string **category**
41
+ (default `"game_topup"`; `"community_reward"` is the other known value).
42
+ Deposits read it back from the on-chain tx; withdrawals sign it into the hash,
43
+ so it must be submitted on-chain verbatim — the bridge handles that. Pass a
44
+ category to any deposit/withdraw call, or omit it for `"game_topup"`. Constants
45
+ live in `@idosgames/core` as `BlockchainOperationCategory`.
46
+
47
+ ## EVM
48
+
49
+ ### 1. Set up the provider
50
+
51
+ `createEvmWalletConfig` builds a wagmi config wired for both browser and mobile
52
+ wallets. Wrap your app with `IDosGamesWalletProvider` (WagmiProvider +
53
+ react-query) once.
54
+
55
+ ```tsx
56
+ import { polygon } from "viem/chains";
57
+ import {
58
+ createEvmWalletConfig,
59
+ IDosGamesWalletProvider,
60
+ } from "@idosgames/wallet/react";
61
+
62
+ const wagmiConfig = createEvmWalletConfig({
63
+ chains: [polygon], // match the EVM networks in your title's blockchain config
64
+ walletConnectProjectId: "<your walletconnect cloud id>", // enables MOBILE wallets
65
+ appName: "My Game",
66
+ });
67
+
68
+ export function Root() {
69
+ return (
70
+ <IDosGamesWalletProvider wagmiConfig={wagmiConfig}>
71
+ <App />
72
+ </IDosGamesWalletProvider>
73
+ );
74
+ }
75
+ ```
76
+
77
+ Connect/disconnect with wagmi's own hooks (`useConnect`, `useAccount`,
78
+ `useDisconnect`) — the `injected()` connector covers MetaMask & browser
79
+ extensions, `walletConnect()` opens the QR/deep-link modal for phones.
80
+
81
+ ### 2. Deposit a token
82
+
83
+ `useEvmBridge(client, titleID)` binds the connected wallet to the four flows.
84
+ Amounts are **raw on-chain units** — scale with viem's `parseUnits`.
85
+
86
+ ```tsx
87
+ import { parseUnits } from "viem";
88
+ import { useEvmBridge } from "@idosgames/wallet/react";
89
+ import type { BlockchainNetworkDefinition } from "@idosgames/core";
90
+
91
+ function DepositButton({ client, network, usdtAddress }) {
92
+ const bridge = useEvmBridge(client, "my-title-id");
93
+
94
+ async function deposit() {
95
+ // approve → depositERC20(token, amount, userID, titleID, category) → report to backend
96
+ const res = await bridge.depositToken({
97
+ network, // BlockchainNetworkDefinition from getDefinitions()
98
+ tokenAddress: usdtAddress, // ERC-20 contract
99
+ amount: parseUnits("25", 6), // 25 USDT (6 decimals) as raw units
100
+ // category defaults to "game_topup"
101
+ });
102
+ if (!res.ok) return alert(`${res.stage}: ${res.error}`);
103
+ // core cache balance is already updated; res.data is DepositTokenResponse
104
+ }
105
+
106
+ return (
107
+ <button disabled={!bridge.connected} onClick={deposit}>
108
+ Deposit 25 USDT
109
+ </button>
110
+ );
111
+ }
112
+ ```
113
+
114
+ ### 3. Withdraw a token
115
+
116
+ ```tsx
117
+ const res = await bridge.withdrawToken({
118
+ currencyID: "usdt",
119
+ networkID: "polygon",
120
+ walletAddress: bridge.account!, // destination — usually the connected wallet
121
+ amount: "25.00", // human decimal; server scales & signs raw units
122
+ });
123
+ if (!res.ok) {
124
+ // If it failed AFTER the debit, res.titleTransactionID is set — recover with
125
+ // retryWithdrawal (while Pending) or confirmWithdrawal, NEVER a fresh request.
126
+ console.error(res.stage, res.error, res.titleTransactionID);
127
+ }
128
+ ```
129
+
130
+ The bridge runs `requestTokenWithdrawal` (debits in-game) → `withdrawERC20`
131
+ on-chain → `confirmWithdrawal`. A `BridgeFailure` tells you exactly where it
132
+ stopped via `stage` (`request` / `withdraw-onchain` / `confirm`) so you can
133
+ recover correctly — see [Failure & recovery](#failure--recovery).
134
+
135
+ ### 4. NFTs
136
+
137
+ ```tsx
138
+ // Deposit: safeTransferFrom(account, pool, id, amount, abi.encode(userID,titleID,category))
139
+ await bridge.depositNft({
140
+ network,
141
+ nftContractAddress,
142
+ tokenId: 42n,
143
+ amount: 1n,
144
+ });
145
+
146
+ // Withdraw: requestNFTWithdrawal → withdrawERC1155 → confirmWithdrawal
147
+ await bridge.withdrawNft({
148
+ itemID,
149
+ networkID: "polygon",
150
+ walletAddress: bridge.account!,
151
+ amount: "1",
152
+ });
153
+ ```
154
+
155
+ ## Solana
156
+
157
+ The Solana RewardPool is a custom program whose instruction/account layout
158
+ isn't in this SDK — so you provide a `SolanaProgramAdapter` (two methods:
159
+ `depositSpl` and `submitWithdrawal`) built with your program's IDL /
160
+ `@solana/web3.js` and the connected wallet from `@solana/wallet-adapter-react`.
161
+ The SDK-side orchestration is identical to EVM.
162
+
163
+ ```tsx
164
+ import {
165
+ SolanaWalletBridgeProvider,
166
+ useSolanaBridge,
167
+ } from "@idosgames/wallet/react";
168
+ import { PhantomWalletAdapter } from "@solana/wallet-adapter-wallets";
169
+ import type { SolanaProgramAdapter } from "@idosgames/wallet";
170
+
171
+ // Wrap (alongside IDosGamesWalletProvider if you also support EVM):
172
+ <SolanaWalletBridgeProvider
173
+ endpoint="https://api.mainnet-beta.solana.com"
174
+ wallets={[new PhantomWalletAdapter()]}
175
+ >
176
+ <App />
177
+ </SolanaWalletBridgeProvider>;
178
+
179
+ // Your program integration:
180
+ const adapter: SolanaProgramAdapter = {
181
+ async depositSpl({ mint, amountRaw, userID, titleID, category }) {
182
+ /* build + send the DepositSpl tx with your IDL; return the signature */
183
+ },
184
+ async submitWithdrawal(sig) {
185
+ /* build + send withdraw_spl with the ed25519 sig-verify ix; return the signature */
186
+ },
187
+ };
188
+
189
+ function Screen({ client }) {
190
+ const bridge = useSolanaBridge(client, "my-title-id", adapter);
191
+ // bridge.depositToken({ network, mint, amountRaw }) / bridge.withdrawToken({ currencyID, networkID, amount })
192
+ }
193
+ ```
194
+
195
+ ## Failure & recovery
196
+
197
+ Every bridge call resolves to a `BridgeResult<T>`:
198
+
199
+ ```ts
200
+ type BridgeResult<T> =
201
+ | { ok: true; onChainTxHash: string; data: T }
202
+ | {
203
+ ok: false;
204
+ stage: BridgeStage; // where it stopped
205
+ error: string;
206
+ onChainTxHash?: string; // set if the asset-moving tx already landed
207
+ titleTransactionID?: string; // set if a withdrawal already debited in-game
208
+ };
209
+ ```
210
+
211
+ Recovery rules (the bridge never double-charges, but you drive the retry):
212
+
213
+ - **`stage: "approve" | "deposit-onchain"`** — nothing was reported; safe to
214
+ retry the whole deposit.
215
+ - **`stage: "report"`** — the on-chain tx (`onChainTxHash`) landed but the
216
+ backend didn't credit it; retry `client.blockchain.depositToken/depositNFT`
217
+ with that hash.
218
+ - **`stage: "withdraw-onchain"` with a `titleTransactionID`** — the withdrawal
219
+ was already debited in-game but not submitted on-chain. Get a fresh signature
220
+ with `client.blockchain.retryWithdrawal(titleTransactionID)` (while `Pending`)
221
+ and submit it with `submitEvmTokenWithdrawal` / `submitEvmNftWithdrawal` —
222
+ **never** call `withdrawToken` again (that debits twice).
223
+ - **`stage: "confirm"` with `onChainTxHash` + `titleTransactionID`** — the tx
224
+ landed but the backend confirm didn't stick; retry
225
+ `client.blockchain.confirmWithdrawal(titleTransactionID, onChainTxHash)`.
226
+
227
+ ## Framework-agnostic core
228
+
229
+ Not on React? Import the same flows from `@idosgames/wallet` and pass viem
230
+ clients yourself:
231
+
232
+ ```ts
233
+ import { depositTokenEvm, withdrawTokenEvm } from "@idosgames/wallet";
234
+
235
+ const clients = { publicClient, walletClient, account }; // your viem clients
236
+ await depositTokenEvm({
237
+ client,
238
+ clients,
239
+ network,
240
+ tokenAddress,
241
+ amount,
242
+ titleID,
243
+ });
244
+ ```
245
+
246
+ ## Notes
247
+
248
+ - The RewardPool ABI here mirrors the backend's `RewardPoolEvmV2` signing
249
+ (field order/names of `withdrawERC20`/`withdrawERC1155`/`depositERC20` must
250
+ match, or signatures fail on-chain).
251
+ - After a deposit/withdrawal the core **balance** cache is fresh, but
252
+ `client.data.user.state.Blockchain` (pending list, stats) is not — call
253
+ `client.blockchain.getUserState()` to refresh it. See the `blockchain-system`
254
+ skill for the full server-side surface, withdrawal gates, and gotchas.
@@ -0,0 +1,269 @@
1
+ import { PublicClient, WalletClient, Address, Abi, ContractFunctionName, ContractFunctionArgs, Hex } from 'viem';
2
+ import { IDosGamesClient, BlockchainNetworkDefinition, DepositNFTResponse, DepositTokenResponse, WithdrawalSignatureResponse, NFTWithdrawalResponse, TokenWithdrawalResponse, SolanaWithdrawalSignature } from '@idosgames/core';
3
+
4
+ /**
5
+ * Where a multi-step bridge flow stopped. Deposits run approve → deposit-onchain → report;
6
+ * withdrawals run request → withdraw-onchain → confirm. Knowing the stage lets a UI recover
7
+ * correctly (e.g. a failed `withdraw-onchain` after a successful `request` means the asset is
8
+ * already debited — offer `retryWithdrawal`, never a fresh request that would debit twice).
9
+ */
10
+ type BridgeStage = "approve" | "deposit-onchain" | "report" | "request" | "withdraw-onchain" | "confirm";
11
+ interface BridgeSuccess<T> {
12
+ ok: true;
13
+ /** Hash/signature of the on-chain transaction that moved the asset (EVM hex or Solana base58). */
14
+ onChainTxHash: string;
15
+ /** The core SDK response that finalized the operation server-side. */
16
+ data: T;
17
+ }
18
+ interface BridgeFailure {
19
+ ok: false;
20
+ stage: BridgeStage;
21
+ error: string;
22
+ /**
23
+ * Set when the asset-moving on-chain tx already landed but a later step failed — the caller can
24
+ * finish the flow with this hash (e.g. re-call `confirmWithdrawal`) instead of restarting.
25
+ */
26
+ onChainTxHash?: string;
27
+ /**
28
+ * Set for a withdrawal whose server-side `request` already succeeded (and already debited the
29
+ * player) but whose on-chain/confirm leg failed. Recover with `client.blockchain.retryWithdrawal`
30
+ * (before ExpiresAt) or `confirmWithdrawal` (if the tx actually landed) — NOT a fresh request.
31
+ */
32
+ titleTransactionID?: string;
33
+ }
34
+ type BridgeResult<T> = BridgeSuccess<T> | BridgeFailure;
35
+ /** Normalizes a thrown value (viem error, plain Error, or unknown) into a short human string. */
36
+ declare function toErrorMessage(e: unknown): string;
37
+ declare function bridgeFail(stage: BridgeStage, error: string, extra?: {
38
+ onChainTxHash?: string;
39
+ titleTransactionID?: string;
40
+ }): BridgeFailure;
41
+ /**
42
+ * Where a wallet-login flow stopped. `challenge` = fetching the message to sign; `sign` = the
43
+ * wallet signing it (user may reject); `login` = exchanging the signature for a session. Unlike
44
+ * a bridge flow there is no on-chain transaction — this is an off-chain proof of ownership.
45
+ */
46
+ type WalletLoginStage = "challenge" | "sign" | "login";
47
+ interface WalletLoginSuccess<T> {
48
+ ok: true;
49
+ /** The core SDK result of the successful login (the fresh ClientState). */
50
+ data: T;
51
+ }
52
+ interface WalletLoginFailure {
53
+ ok: false;
54
+ stage: WalletLoginStage;
55
+ error: string;
56
+ }
57
+ type WalletLoginResult<T> = WalletLoginSuccess<T> | WalletLoginFailure;
58
+ declare function walletLoginFail(stage: WalletLoginStage, error: string): WalletLoginFailure;
59
+
60
+ /**
61
+ * The viem clients + signing account the EVM bridge needs. wagmi supplies all three:
62
+ * `usePublicClient()`, `useWalletClient().data`, and `useAccount().address`. Kept as plain viem
63
+ * types so the framework-agnostic core never imports wagmi/React.
64
+ */
65
+ interface EvmBridgeClients {
66
+ publicClient: PublicClient;
67
+ walletClient: WalletClient;
68
+ /** The connected wallet address that signs and pays for the transactions. */
69
+ account: Address;
70
+ }
71
+ /**
72
+ * Sends a contract write and waits for its receipt, returning the tx hash. Throws if the
73
+ * transaction reverts on-chain (so callers can attribute the failure to the on-chain stage).
74
+ */
75
+ declare function writeAndWait<const TAbi extends Abi, TFunctionName extends ContractFunctionName<TAbi, "nonpayable" | "payable">>(clients: EvmBridgeClients, request: {
76
+ address: Address;
77
+ abi: TAbi;
78
+ functionName: TFunctionName;
79
+ args: ContractFunctionArgs<TAbi, "nonpayable" | "payable", TFunctionName>;
80
+ value?: bigint;
81
+ }): Promise<Hex>;
82
+
83
+ /**
84
+ * Ensures the RewardPool is allowed to pull at least `amount` of an ERC-20 from `account`.
85
+ * Reads the current allowance and only sends an `approve` when it's short. Returns the approve
86
+ * tx hash if one was sent, or null when the existing allowance already covered the amount.
87
+ */
88
+ declare function ensureErc20Allowance(clients: EvmBridgeClients, tokenAddress: Address, spender: Address, amount: bigint): Promise<Hex | null>;
89
+ interface DepositTokenEvmParams {
90
+ client: IDosGamesClient;
91
+ clients: EvmBridgeClients;
92
+ network: BlockchainNetworkDefinition;
93
+ /** ERC-20 contract of the token being deposited (the RewardPool splits/credits it in-game). */
94
+ tokenAddress: Address;
95
+ /** Raw on-chain amount, already scaled by the token's decimals (use viem `parseUnits`). */
96
+ amount: bigint;
97
+ /** The title the client was created for (not exposed on the client — pass it through). */
98
+ titleID: string;
99
+ /** Operation kind; defaults to "game_topup" server-side. Deposits echo it into the tx. */
100
+ category?: string;
101
+ }
102
+ /**
103
+ * Full EVM token-deposit flow: approve (if needed) → `depositERC20(token, amount, userID,
104
+ * titleID, category)` on the RewardPool → report the tx hash to the backend so it verifies the
105
+ * transfer and credits the in-game crypto balance. On success the core cache balance is already
106
+ * updated by `client.blockchain.depositToken`.
107
+ */
108
+ declare function depositTokenEvm(params: DepositTokenEvmParams): Promise<BridgeResult<DepositTokenResponse>>;
109
+ interface DepositNftEvmParams {
110
+ client: IDosGamesClient;
111
+ clients: EvmBridgeClients;
112
+ network: BlockchainNetworkDefinition;
113
+ /** ERC-1155 collection contract holding the NFT. */
114
+ nftContractAddress: Address;
115
+ /** On-chain token id of the NFT being deposited. */
116
+ tokenId: bigint;
117
+ /** Copies to transfer (1 for a unique NFT; ERC-1155 collections can hold fungible editions). */
118
+ amount: bigint;
119
+ titleID: string;
120
+ category?: string;
121
+ }
122
+ /**
123
+ * Full EVM NFT-deposit flow: `safeTransferFrom(account, pool, id, amount, data)` on the ERC-1155
124
+ * collection — where `data = abi.encode(userID, titleID, category)` — then report the tx hash so
125
+ * the backend verifies the transfer and grants the matching in-game item. No operator approval is
126
+ * needed: the player transfers their own token, so msg.sender == from.
127
+ */
128
+ declare function depositNftEvm(params: DepositNftEvmParams): Promise<BridgeResult<DepositNFTResponse>>;
129
+ interface DepositNft721EvmParams {
130
+ client: IDosGamesClient;
131
+ clients: EvmBridgeClients;
132
+ network: BlockchainNetworkDefinition;
133
+ /** ERC-721 collection contract holding the NFT. */
134
+ nftContractAddress: Address;
135
+ /** On-chain token id of the unique NFT being deposited. */
136
+ tokenId: bigint;
137
+ titleID: string;
138
+ category?: string;
139
+ }
140
+ /**
141
+ * Full EVM ERC-721 NFT-deposit flow: `safeTransferFrom(account, pool, tokenId, data)` on the
142
+ * ERC-721 collection — where `data = abi.encode(userID, titleID, category)` — then report the tx
143
+ * hash so the backend verifies the transfer and grants the matching in-game unique item. No
144
+ * operator approval is needed: the player transfers their own token, so msg.sender == from.
145
+ */
146
+ declare function depositNftEvm721(params: DepositNft721EvmParams): Promise<BridgeResult<DepositNFTResponse>>;
147
+
148
+ /**
149
+ * Submits a server-signed ERC-20 withdrawal on-chain by calling `withdrawERC20` on the RewardPool.
150
+ * Every field comes straight from the server's {@link WithdrawalSignatureResponse}; the client
151
+ * only echoes them (Amount and Nonce are decimal strings the server already scaled to raw units,
152
+ * and userID/titleID/category are part of the signed hash — passing anything else reverts). Use
153
+ * this directly to submit a fresh signature from `retryWithdrawal`.
154
+ */
155
+ declare function submitEvmTokenWithdrawal(clients: EvmBridgeClients, sig: WithdrawalSignatureResponse): Promise<Hex>;
156
+ /**
157
+ * Submits a server-signed ERC-1155 game-NFT withdrawal on-chain. The v2 backend signs a MINT voucher
158
+ * (tag "ERC1155_MINT") against the ItemBridge — `sig.ContractAddress` is the bridge and
159
+ * `sig.TokenAddress` is the collection — so this calls `withdrawERC1155Mint`, NOT RewardPool's
160
+ * `withdrawERC1155` (which would fail the selector/hash-tag check).
161
+ */
162
+ declare function submitEvmNftWithdrawal(clients: EvmBridgeClients, sig: WithdrawalSignatureResponse): Promise<Hex>;
163
+ /**
164
+ * Submits a server-signed ERC-721 unique game-NFT withdrawal on-chain via the ItemBridge's
165
+ * `withdrawERC721Mint` (MINT voucher, tag "ERC721_MINT"; `sig.ContractAddress` = bridge,
166
+ * `sig.TokenAddress` = collection) — not RewardPool's custody `withdrawERC721`.
167
+ */
168
+ declare function submitEvmNftWithdrawal721(clients: EvmBridgeClients, sig: WithdrawalSignatureResponse): Promise<Hex>;
169
+ interface WithdrawTokenEvmParams {
170
+ client: IDosGamesClient;
171
+ clients: EvmBridgeClients;
172
+ currencyID: string;
173
+ networkID: string;
174
+ /** Destination wallet — usually the connected `clients.account`. */
175
+ walletAddress: string;
176
+ /** Human decimal amount to withdraw (the server converts and signs raw units). */
177
+ amount: string;
178
+ category?: string;
179
+ }
180
+ /**
181
+ * Full EVM token-withdrawal flow: `requestTokenWithdrawal` (debits in-game immediately and returns
182
+ * a signed payload) → `withdrawERC20` on-chain → `confirmWithdrawal` with the resulting hash.
183
+ *
184
+ * On a failure AFTER the request succeeded, the returned {@link BridgeFailure} carries
185
+ * `titleTransactionID` (the asset is already debited — recover with `retryWithdrawal` while
186
+ * Pending, or `confirmWithdrawal` if the tx actually landed) and, when the on-chain leg landed,
187
+ * `onChainTxHash`. Never restart with a fresh `requestTokenWithdrawal` — that debits twice.
188
+ */
189
+ declare function withdrawTokenEvm(params: WithdrawTokenEvmParams): Promise<BridgeResult<TokenWithdrawalResponse>>;
190
+ interface WithdrawNftEvmParams {
191
+ client: IDosGamesClient;
192
+ clients: EvmBridgeClients;
193
+ itemID: string;
194
+ networkID: string;
195
+ walletAddress: string;
196
+ /** Copies to withdraw, as an integer string (usually "1"). */
197
+ amount: string;
198
+ category?: string;
199
+ }
200
+ /** Full EVM NFT-withdrawal flow: `requestNFTWithdrawal` → `withdrawERC1155` → `confirmWithdrawal`. */
201
+ declare function withdrawNftEvm(params: WithdrawNftEvmParams): Promise<BridgeResult<NFTWithdrawalResponse>>;
202
+
203
+ /**
204
+ * The on-chain half of the Solana bridge, delegated to the title's own program integration.
205
+ *
206
+ * Unlike EVM — where the RewardPool ABI is fully known and viem builds the calls — the Solana
207
+ * RewardPool is a custom program whose instruction/account layout (DepositSpl, withdraw_spl + the
208
+ * ed25519 sig-verify instruction) lives in that program's IDL, NOT in this client SDK. So the
209
+ * bridge asks you to provide these two calls, built with your program's IDL / `@solana/web3.js`
210
+ * (or Anchor) against the connected wallet from `@solana/wallet-adapter-react`. The SDK-side
211
+ * orchestration (request → submit → confirm, deposit → report) is identical to EVM and handled by
212
+ * {@link depositTokenSolana} / {@link withdrawTokenSolana}.
213
+ */
214
+ interface SolanaProgramAdapter {
215
+ /**
216
+ * Builds and sends the on-chain `DepositSpl` transfer of `amountRaw` base units of `mint` into
217
+ * the platform program pool, embedding the identifiers the backend reads back
218
+ * (`GetDepositSplCallDetailsBySignature` verifies `userID`). Returns the transaction signature.
219
+ */
220
+ depositSpl(params: {
221
+ mint: string;
222
+ amountRaw: bigint;
223
+ userID: string;
224
+ titleID: string;
225
+ category: string;
226
+ }): Promise<string>;
227
+ /**
228
+ * Builds and sends the on-chain `withdraw_spl` transaction from a server-issued signature
229
+ * payload — including the ed25519 sig-verify instruction at `SigIxIndex` carrying
230
+ * `Ed25519PublicKey`/`Ed25519Message`/`SignatureHex`. Returns the transaction signature.
231
+ */
232
+ submitWithdrawal(sig: SolanaWithdrawalSignature): Promise<string>;
233
+ }
234
+
235
+ interface DepositTokenSolanaParams {
236
+ client: IDosGamesClient;
237
+ adapter: SolanaProgramAdapter;
238
+ network: BlockchainNetworkDefinition;
239
+ /** SPL mint of the token being deposited. */
240
+ mint: string;
241
+ /** Raw base-unit amount (already scaled by the mint's decimals). */
242
+ amountRaw: bigint;
243
+ titleID: string;
244
+ category?: string;
245
+ }
246
+ /**
247
+ * Full Solana token-deposit flow: your {@link SolanaProgramAdapter.depositSpl} sends the on-chain
248
+ * transfer, then `client.blockchain.depositToken` reports the signature so the backend verifies
249
+ * and credits the in-game balance. Mirrors {@link depositTokenEvm}.
250
+ */
251
+ declare function depositTokenSolana(params: DepositTokenSolanaParams): Promise<BridgeResult<DepositTokenResponse>>;
252
+ interface WithdrawTokenSolanaParams {
253
+ client: IDosGamesClient;
254
+ adapter: SolanaProgramAdapter;
255
+ currencyID: string;
256
+ networkID: string;
257
+ walletAddress: string;
258
+ amount: string;
259
+ category?: string;
260
+ }
261
+ /**
262
+ * Full Solana token-withdrawal flow: `requestTokenWithdrawal` → your
263
+ * {@link SolanaProgramAdapter.submitWithdrawal} sends the `withdraw_spl` tx → `confirmWithdrawal`.
264
+ * Same recovery semantics as EVM: a post-request failure carries `titleTransactionID` (already
265
+ * debited — retry, don't re-request). Mirrors {@link withdrawTokenEvm}.
266
+ */
267
+ declare function withdrawTokenSolana(params: WithdrawTokenSolanaParams): Promise<BridgeResult<TokenWithdrawalResponse>>;
268
+
269
+ export { writeAndWait as A, type BridgeFailure as B, type DepositNft721EvmParams as D, type EvmBridgeClients as E, type SolanaProgramAdapter as S, type WalletLoginResult as W, type BridgeResult as a, type BridgeStage as b, type BridgeSuccess as c, type DepositNftEvmParams as d, type DepositTokenEvmParams as e, type DepositTokenSolanaParams as f, type WalletLoginFailure as g, type WalletLoginStage as h, type WalletLoginSuccess as i, type WithdrawNftEvmParams as j, type WithdrawTokenEvmParams as k, type WithdrawTokenSolanaParams as l, bridgeFail as m, depositNftEvm as n, depositNftEvm721 as o, depositTokenEvm as p, depositTokenSolana as q, ensureErc20Allowance as r, submitEvmNftWithdrawal as s, submitEvmNftWithdrawal721 as t, submitEvmTokenWithdrawal as u, toErrorMessage as v, walletLoginFail as w, withdrawNftEvm as x, withdrawTokenEvm as y, withdrawTokenSolana as z };