@avalabs/avacloud-waas-react 1.0.12 → 1.0.14-nightly.20250704
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 +76 -0
- package/dist/index.d.mts +100 -2
- package/dist/index.d.ts +100 -2
- package/dist/index.js +400 -0
- package/dist/index.mjs +386 -0
- package/package.json +14 -10
package/README.md
CHANGED
|
@@ -209,6 +209,82 @@ Hook for accessing and setting the current chain ID.
|
|
|
209
209
|
const { chainId, setChainId } = useChainId();
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
+
### useGaslessTransaction
|
|
213
|
+
|
|
214
|
+
Hook for sending gasless (meta-)transactions through AvaCloud's gas relayer.
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
import { useGaslessTransaction, useGlacier } from '@avalabs/avacloud-waas-react';
|
|
218
|
+
|
|
219
|
+
function CounterExample() {
|
|
220
|
+
// Retrieve the current subnet RPC URL from Glacier
|
|
221
|
+
const { blockchain } = useGlacier();
|
|
222
|
+
|
|
223
|
+
const gaslessConfig = {
|
|
224
|
+
relayerUrl: 'https://gas-relayer.avax-test.network/printedapr/testnet/rpc', // AvaCloud relayer RPC
|
|
225
|
+
subnetRpcUrl: blockchain?.rpcUrl || '', // Target subnet RPC
|
|
226
|
+
forwarderAddress: '0x52ec85e43d09889b2bf9e431935356e06f023680', // AvaCloud forwarder
|
|
227
|
+
domainName: 'Counter',
|
|
228
|
+
domainVersion: '1',
|
|
229
|
+
requestType: 'Message',
|
|
230
|
+
suffixType: 'bytes32', // Optional – request suffix type
|
|
231
|
+
suffixName: 'XMKUCJONOFSUSFCYHTYHCLX', // Optional – request suffix name
|
|
232
|
+
} as const;
|
|
233
|
+
|
|
234
|
+
// Counter contract information
|
|
235
|
+
const COUNTER_CONTRACT_ADDRESS = '0xe4bB5F15dc278197FcE9B21e5aC0442a95e25b5f';
|
|
236
|
+
const COUNTER_INCREMENT_ABI = [
|
|
237
|
+
{
|
|
238
|
+
inputs: [],
|
|
239
|
+
name: 'increment',
|
|
240
|
+
outputs: [],
|
|
241
|
+
stateMutability: 'nonpayable',
|
|
242
|
+
type: 'function',
|
|
243
|
+
},
|
|
244
|
+
] as const;
|
|
245
|
+
|
|
246
|
+
const {
|
|
247
|
+
sendGaslessTransaction,
|
|
248
|
+
isLoading,
|
|
249
|
+
error,
|
|
250
|
+
txHash,
|
|
251
|
+
reset,
|
|
252
|
+
} = useGaslessTransaction({
|
|
253
|
+
gaslessConfig,
|
|
254
|
+
contractAddress: COUNTER_CONTRACT_ADDRESS,
|
|
255
|
+
abi: COUNTER_INCREMENT_ABI,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const handleIncrement = () =>
|
|
259
|
+
sendGaslessTransaction({ functionName: 'increment' });
|
|
260
|
+
|
|
261
|
+
return (
|
|
262
|
+
<div>
|
|
263
|
+
<button onClick={handleIncrement} disabled={isLoading}>
|
|
264
|
+
Increment counter (no gas)
|
|
265
|
+
</button>
|
|
266
|
+
|
|
267
|
+
{isLoading && <p>Sending transaction…</p>}
|
|
268
|
+
{txHash && <p>Transaction hash: {txHash}</p>}
|
|
269
|
+
{error && <p style={{ color: 'red' }}>{error}</p>}
|
|
270
|
+
|
|
271
|
+
<button onClick={reset}>Reset</button>
|
|
272
|
+
</div>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Parameters returned by the hook**
|
|
278
|
+
|
|
279
|
+
| Property | Type | Description |
|
|
280
|
+
|----------|------|-------------|
|
|
281
|
+
| `sendGaslessTransaction` | `(params: { functionName: string; args?: unknown[]; abi?: unknown; contractAddress?: string }) => Promise<void>` | Sends the meta-transaction |
|
|
282
|
+
| `isLoading` | `boolean` | `true` while the transaction is being prepared or broadcast |
|
|
283
|
+
| `error` | `string \| null` | Error message, if any |
|
|
284
|
+
| `txHash` | `string \| null` | Transaction hash once broadcast |
|
|
285
|
+
| `reset` | `() => void` | Resets the hook state |
|
|
286
|
+
|
|
287
|
+
|
|
212
288
|
## WAGMI Integration
|
|
213
289
|
|
|
214
290
|
This SDK includes a WAGMI connector that allows you to use AvaCloud wallets with WAGMI (React Ethereum Library).
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _cubist_labs_cubesigner_sdk from '@cubist-labs/cubesigner-sdk';
|
|
3
3
|
import { CubeSignerClient, IdentityProof } from '@cubist-labs/cubesigner-sdk';
|
|
4
|
-
import { PropsWithChildren, ButtonHTMLAttributes } from 'react';
|
|
4
|
+
import { PropsWithChildren, ButtonHTMLAttributes, ReactNode } from 'react';
|
|
5
5
|
import { ButtonProps } from '@avalabs/core-k2-components';
|
|
6
6
|
import { Hex, Signature, TransactionRequest, Hash } from 'viem';
|
|
7
|
+
import * as _tanstack_react_query_build_legacy_types from '@tanstack/react-query/build/legacy/types';
|
|
7
8
|
import { CreateConnectorFn } from '@wagmi/core';
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -366,6 +367,32 @@ interface WalletCardProps {
|
|
|
366
367
|
}
|
|
367
368
|
declare function WalletCard({ onClose }: WalletCardProps): react_jsx_runtime.JSX.Element | null;
|
|
368
369
|
|
|
370
|
+
interface BlockchainData {
|
|
371
|
+
chainId: string;
|
|
372
|
+
chainName: string;
|
|
373
|
+
description: string;
|
|
374
|
+
platformChainId: string;
|
|
375
|
+
subnetId: string;
|
|
376
|
+
vmId: string;
|
|
377
|
+
vmName: string;
|
|
378
|
+
explorerUrl: string;
|
|
379
|
+
rpcUrl: string;
|
|
380
|
+
wsUrl: string;
|
|
381
|
+
isTestnet: boolean;
|
|
382
|
+
utilityAddresses: {
|
|
383
|
+
multicall: string;
|
|
384
|
+
};
|
|
385
|
+
networkToken: {
|
|
386
|
+
name: string;
|
|
387
|
+
symbol: string;
|
|
388
|
+
decimals: number;
|
|
389
|
+
logoUri: string;
|
|
390
|
+
description: string;
|
|
391
|
+
};
|
|
392
|
+
chainLogoUri: string;
|
|
393
|
+
private: boolean;
|
|
394
|
+
enabledFeatures: string[];
|
|
395
|
+
}
|
|
369
396
|
interface TokenReputation {
|
|
370
397
|
verified: boolean;
|
|
371
398
|
popular: boolean;
|
|
@@ -519,6 +546,77 @@ interface UseUserWalletsResult {
|
|
|
519
546
|
}
|
|
520
547
|
declare function useUserWallets(): UseUserWalletsResult;
|
|
521
548
|
|
|
549
|
+
declare function useGlacier(): {
|
|
550
|
+
balance: string;
|
|
551
|
+
isLoadingBalance: boolean;
|
|
552
|
+
currencySymbol: string;
|
|
553
|
+
blockchain: BlockchainData | undefined;
|
|
554
|
+
};
|
|
555
|
+
declare function useBlockchain(chainId: string): _tanstack_react_query_build_legacy_types.UseQueryResult<BlockchainData, Error>;
|
|
556
|
+
|
|
522
557
|
declare function avaCloudWallet(): CreateConnectorFn;
|
|
523
558
|
|
|
524
|
-
|
|
559
|
+
interface GaslessConfig {
|
|
560
|
+
/** URL of the AvaCloud gasless relayer RPC endpoint */
|
|
561
|
+
relayerUrl: string;
|
|
562
|
+
/** Public JSON-RPC endpoint of the target subnet */
|
|
563
|
+
subnetRpcUrl: string;
|
|
564
|
+
/** Forwarder contract address provided by AvaCloud */
|
|
565
|
+
forwarderAddress: string;
|
|
566
|
+
/** EIP-712 domain name, e.g. "domain" */
|
|
567
|
+
domainName: string;
|
|
568
|
+
/** EIP-712 domain version, e.g. "1" */
|
|
569
|
+
domainVersion: string;
|
|
570
|
+
/** Primary type for the request, e.g. "Message" */
|
|
571
|
+
requestType: string;
|
|
572
|
+
/** Suffix for the request in format "type name" (e.g. "bytes32 XMKUCJONOFSUSFCYHTYHCLX") */
|
|
573
|
+
suffix?: string;
|
|
574
|
+
}
|
|
575
|
+
interface FetchGaslessConfigParams {
|
|
576
|
+
orgId: string;
|
|
577
|
+
subnetId: string;
|
|
578
|
+
}
|
|
579
|
+
interface GaslessProviderProps {
|
|
580
|
+
children: ReactNode;
|
|
581
|
+
/** Optional pre-fetched config (skip network fetch when supplied) */
|
|
582
|
+
config?: GaslessConfig;
|
|
583
|
+
/** Parameters required to fetch config from the auth service */
|
|
584
|
+
fetchParams?: FetchGaslessConfigParams;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* GaslessProvider – supplies gasless relayer configuration to hooks
|
|
588
|
+
*
|
|
589
|
+
* NOTE: For security reasons, this provider expects the configuration to be
|
|
590
|
+
* provided by the integrator. The intention is that your backend (or
|
|
591
|
+
* another trusted environment) fetches the relayer configuration via
|
|
592
|
+
* AvaCloud's internal endpoint and forwards the non-sensitive parts
|
|
593
|
+
* (relayer URL, forwarder address, etc.) to the browser.
|
|
594
|
+
*/
|
|
595
|
+
declare function GaslessProvider({ children, config, fetchParams }: GaslessProviderProps): react_jsx_runtime.JSX.Element;
|
|
596
|
+
|
|
597
|
+
interface GaslessTxState {
|
|
598
|
+
isLoading: boolean;
|
|
599
|
+
error: string | null;
|
|
600
|
+
txHash: string | null;
|
|
601
|
+
}
|
|
602
|
+
interface SendGaslessTransactionParams {
|
|
603
|
+
functionName: string;
|
|
604
|
+
args?: unknown[];
|
|
605
|
+
abi?: unknown;
|
|
606
|
+
contractAddress?: string;
|
|
607
|
+
}
|
|
608
|
+
interface UseGaslessTransactionReturn extends GaslessTxState {
|
|
609
|
+
sendGaslessTransaction: (params: SendGaslessTransactionParams) => Promise<void>;
|
|
610
|
+
reset: () => void;
|
|
611
|
+
}
|
|
612
|
+
interface UseGaslessTransactionOptions {
|
|
613
|
+
/** Gasless transaction configuration */
|
|
614
|
+
gaslessConfig: GaslessConfig;
|
|
615
|
+
/** Default contract address (can be overridden per call) */
|
|
616
|
+
contractAddress?: string;
|
|
617
|
+
/** Default ABI (can be overridden per call) */
|
|
618
|
+
abi?: unknown;
|
|
619
|
+
}
|
|
620
|
+
declare function useGaslessTransaction({ gaslessConfig, contractAddress: defaultContractAddress, abi: defaultAbi }: UseGaslessTransactionOptions): UseGaslessTransactionReturn;
|
|
621
|
+
|
|
622
|
+
export { type AddAccountMessage, type AdminPortalSettings, type Auth0User, type AuthMessage, type AuthMessagePayload, type AuthStateUpdateMessage, type AuthStatusMessage, type AvaCloudEnvironment, type AvaCloudWalletContextType, AvaCloudWalletProvider, type AvaCloudWalletProviderProps, type BaseAuthMessage, type CheckAuthStatusMessage, type CubistWalletInfo, type ErrorMessage, ExportView, GaslessProvider, type GetOidcMessage, type IframeReadyMessage, LoginButton, type LoginRequestMessage, type LogoutRequestMessage, type MessageType, type OrgConfig, type ReceiveOidcMessage, ReceiveView, type RegisterMessage, type RegisterPayload, type RegisterSuccessMessage, SendView, type SignupRequestMessage, ThemeProvider, TokensView, type UserInfo, UserProfile, VM, WalletButton, WalletCard, WalletDisplay, type WalletInfo, type WalletKeysErrorMessage, type WalletKeysUpdateMessage, avaCloudWallet, useAuth, useAvaCloudWallet, useBlockchain, useChainId, useGaslessTransaction, useGlacier, usePostMessage, useSignMessage, useSignTransaction, useThemeMode, useTransferTokens, useUserWallets };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _cubist_labs_cubesigner_sdk from '@cubist-labs/cubesigner-sdk';
|
|
3
3
|
import { CubeSignerClient, IdentityProof } from '@cubist-labs/cubesigner-sdk';
|
|
4
|
-
import { PropsWithChildren, ButtonHTMLAttributes } from 'react';
|
|
4
|
+
import { PropsWithChildren, ButtonHTMLAttributes, ReactNode } from 'react';
|
|
5
5
|
import { ButtonProps } from '@avalabs/core-k2-components';
|
|
6
6
|
import { Hex, Signature, TransactionRequest, Hash } from 'viem';
|
|
7
|
+
import * as _tanstack_react_query_build_legacy_types from '@tanstack/react-query/build/legacy/types';
|
|
7
8
|
import { CreateConnectorFn } from '@wagmi/core';
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -366,6 +367,32 @@ interface WalletCardProps {
|
|
|
366
367
|
}
|
|
367
368
|
declare function WalletCard({ onClose }: WalletCardProps): react_jsx_runtime.JSX.Element | null;
|
|
368
369
|
|
|
370
|
+
interface BlockchainData {
|
|
371
|
+
chainId: string;
|
|
372
|
+
chainName: string;
|
|
373
|
+
description: string;
|
|
374
|
+
platformChainId: string;
|
|
375
|
+
subnetId: string;
|
|
376
|
+
vmId: string;
|
|
377
|
+
vmName: string;
|
|
378
|
+
explorerUrl: string;
|
|
379
|
+
rpcUrl: string;
|
|
380
|
+
wsUrl: string;
|
|
381
|
+
isTestnet: boolean;
|
|
382
|
+
utilityAddresses: {
|
|
383
|
+
multicall: string;
|
|
384
|
+
};
|
|
385
|
+
networkToken: {
|
|
386
|
+
name: string;
|
|
387
|
+
symbol: string;
|
|
388
|
+
decimals: number;
|
|
389
|
+
logoUri: string;
|
|
390
|
+
description: string;
|
|
391
|
+
};
|
|
392
|
+
chainLogoUri: string;
|
|
393
|
+
private: boolean;
|
|
394
|
+
enabledFeatures: string[];
|
|
395
|
+
}
|
|
369
396
|
interface TokenReputation {
|
|
370
397
|
verified: boolean;
|
|
371
398
|
popular: boolean;
|
|
@@ -519,6 +546,77 @@ interface UseUserWalletsResult {
|
|
|
519
546
|
}
|
|
520
547
|
declare function useUserWallets(): UseUserWalletsResult;
|
|
521
548
|
|
|
549
|
+
declare function useGlacier(): {
|
|
550
|
+
balance: string;
|
|
551
|
+
isLoadingBalance: boolean;
|
|
552
|
+
currencySymbol: string;
|
|
553
|
+
blockchain: BlockchainData | undefined;
|
|
554
|
+
};
|
|
555
|
+
declare function useBlockchain(chainId: string): _tanstack_react_query_build_legacy_types.UseQueryResult<BlockchainData, Error>;
|
|
556
|
+
|
|
522
557
|
declare function avaCloudWallet(): CreateConnectorFn;
|
|
523
558
|
|
|
524
|
-
|
|
559
|
+
interface GaslessConfig {
|
|
560
|
+
/** URL of the AvaCloud gasless relayer RPC endpoint */
|
|
561
|
+
relayerUrl: string;
|
|
562
|
+
/** Public JSON-RPC endpoint of the target subnet */
|
|
563
|
+
subnetRpcUrl: string;
|
|
564
|
+
/** Forwarder contract address provided by AvaCloud */
|
|
565
|
+
forwarderAddress: string;
|
|
566
|
+
/** EIP-712 domain name, e.g. "domain" */
|
|
567
|
+
domainName: string;
|
|
568
|
+
/** EIP-712 domain version, e.g. "1" */
|
|
569
|
+
domainVersion: string;
|
|
570
|
+
/** Primary type for the request, e.g. "Message" */
|
|
571
|
+
requestType: string;
|
|
572
|
+
/** Suffix for the request in format "type name" (e.g. "bytes32 XMKUCJONOFSUSFCYHTYHCLX") */
|
|
573
|
+
suffix?: string;
|
|
574
|
+
}
|
|
575
|
+
interface FetchGaslessConfigParams {
|
|
576
|
+
orgId: string;
|
|
577
|
+
subnetId: string;
|
|
578
|
+
}
|
|
579
|
+
interface GaslessProviderProps {
|
|
580
|
+
children: ReactNode;
|
|
581
|
+
/** Optional pre-fetched config (skip network fetch when supplied) */
|
|
582
|
+
config?: GaslessConfig;
|
|
583
|
+
/** Parameters required to fetch config from the auth service */
|
|
584
|
+
fetchParams?: FetchGaslessConfigParams;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* GaslessProvider – supplies gasless relayer configuration to hooks
|
|
588
|
+
*
|
|
589
|
+
* NOTE: For security reasons, this provider expects the configuration to be
|
|
590
|
+
* provided by the integrator. The intention is that your backend (or
|
|
591
|
+
* another trusted environment) fetches the relayer configuration via
|
|
592
|
+
* AvaCloud's internal endpoint and forwards the non-sensitive parts
|
|
593
|
+
* (relayer URL, forwarder address, etc.) to the browser.
|
|
594
|
+
*/
|
|
595
|
+
declare function GaslessProvider({ children, config, fetchParams }: GaslessProviderProps): react_jsx_runtime.JSX.Element;
|
|
596
|
+
|
|
597
|
+
interface GaslessTxState {
|
|
598
|
+
isLoading: boolean;
|
|
599
|
+
error: string | null;
|
|
600
|
+
txHash: string | null;
|
|
601
|
+
}
|
|
602
|
+
interface SendGaslessTransactionParams {
|
|
603
|
+
functionName: string;
|
|
604
|
+
args?: unknown[];
|
|
605
|
+
abi?: unknown;
|
|
606
|
+
contractAddress?: string;
|
|
607
|
+
}
|
|
608
|
+
interface UseGaslessTransactionReturn extends GaslessTxState {
|
|
609
|
+
sendGaslessTransaction: (params: SendGaslessTransactionParams) => Promise<void>;
|
|
610
|
+
reset: () => void;
|
|
611
|
+
}
|
|
612
|
+
interface UseGaslessTransactionOptions {
|
|
613
|
+
/** Gasless transaction configuration */
|
|
614
|
+
gaslessConfig: GaslessConfig;
|
|
615
|
+
/** Default contract address (can be overridden per call) */
|
|
616
|
+
contractAddress?: string;
|
|
617
|
+
/** Default ABI (can be overridden per call) */
|
|
618
|
+
abi?: unknown;
|
|
619
|
+
}
|
|
620
|
+
declare function useGaslessTransaction({ gaslessConfig, contractAddress: defaultContractAddress, abi: defaultAbi }: UseGaslessTransactionOptions): UseGaslessTransactionReturn;
|
|
621
|
+
|
|
622
|
+
export { type AddAccountMessage, type AdminPortalSettings, type Auth0User, type AuthMessage, type AuthMessagePayload, type AuthStateUpdateMessage, type AuthStatusMessage, type AvaCloudEnvironment, type AvaCloudWalletContextType, AvaCloudWalletProvider, type AvaCloudWalletProviderProps, type BaseAuthMessage, type CheckAuthStatusMessage, type CubistWalletInfo, type ErrorMessage, ExportView, GaslessProvider, type GetOidcMessage, type IframeReadyMessage, LoginButton, type LoginRequestMessage, type LogoutRequestMessage, type MessageType, type OrgConfig, type ReceiveOidcMessage, ReceiveView, type RegisterMessage, type RegisterPayload, type RegisterSuccessMessage, SendView, type SignupRequestMessage, ThemeProvider, TokensView, type UserInfo, UserProfile, VM, WalletButton, WalletCard, WalletDisplay, type WalletInfo, type WalletKeysErrorMessage, type WalletKeysUpdateMessage, avaCloudWallet, useAuth, useAvaCloudWallet, useBlockchain, useChainId, useGaslessTransaction, useGlacier, usePostMessage, useSignMessage, useSignTransaction, useThemeMode, useTransferTokens, useUserWallets };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -22,6 +32,7 @@ var index_exports = {};
|
|
|
22
32
|
__export(index_exports, {
|
|
23
33
|
AvaCloudWalletProvider: () => AvaCloudWalletProvider,
|
|
24
34
|
ExportView: () => ExportView,
|
|
35
|
+
GaslessProvider: () => GaslessProvider,
|
|
25
36
|
LoginButton: () => LoginButton,
|
|
26
37
|
ReceiveView: () => ReceiveView,
|
|
27
38
|
SendView: () => SendView,
|
|
@@ -35,7 +46,10 @@ __export(index_exports, {
|
|
|
35
46
|
avaCloudWallet: () => avaCloudWallet,
|
|
36
47
|
useAuth: () => useAuth,
|
|
37
48
|
useAvaCloudWallet: () => useAvaCloudWallet,
|
|
49
|
+
useBlockchain: () => useBlockchain,
|
|
38
50
|
useChainId: () => useChainId,
|
|
51
|
+
useGaslessTransaction: () => useGaslessTransaction,
|
|
52
|
+
useGlacier: () => useGlacier,
|
|
39
53
|
usePostMessage: () => usePostMessage,
|
|
40
54
|
useSignMessage: () => useSignMessage,
|
|
41
55
|
useSignTransaction: () => useSignTransaction,
|
|
@@ -1628,6 +1642,10 @@ function AvaCloudWalletProvider({
|
|
|
1628
1642
|
onAuthError,
|
|
1629
1643
|
onWalletUpdate
|
|
1630
1644
|
}) {
|
|
1645
|
+
const { setChainId } = useChainId();
|
|
1646
|
+
(0, import_react9.useEffect)(() => {
|
|
1647
|
+
setChainId(chainId);
|
|
1648
|
+
}, [chainId, setChainId]);
|
|
1631
1649
|
const authServiceUrl = env === "development" ? "http://localhost:3000" : env === "staging" ? "https://ac-auth-service-env-staging-ava-labs.vercel.app" : "https://ac-auth-service.vercel.app";
|
|
1632
1650
|
const environment = env;
|
|
1633
1651
|
const [isAuthenticated, setIsAuthenticated] = (0, import_react9.useState)(false);
|
|
@@ -4587,10 +4605,389 @@ function avaCloudWallet() {
|
|
|
4587
4605
|
}
|
|
4588
4606
|
}));
|
|
4589
4607
|
}
|
|
4608
|
+
|
|
4609
|
+
// src/providers/GaslessProvider.tsx
|
|
4610
|
+
var import_react27 = require("react");
|
|
4611
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
4612
|
+
function validateGaslessConfig(config) {
|
|
4613
|
+
if (!config || typeof config !== "object") {
|
|
4614
|
+
return "Invalid gasless configuration: expected an object";
|
|
4615
|
+
}
|
|
4616
|
+
const requiredFields = [
|
|
4617
|
+
{ field: "relayerUrl", description: "Relayer RPC URL" },
|
|
4618
|
+
{ field: "subnetRpcUrl", description: "Subnet RPC URL" },
|
|
4619
|
+
{ field: "forwarderAddress", description: "Forwarder contract address" },
|
|
4620
|
+
{ field: "domainName", description: "EIP-712 domain name" },
|
|
4621
|
+
{ field: "domainVersion", description: "EIP-712 domain version" },
|
|
4622
|
+
{ field: "requestType", description: "Request type name" }
|
|
4623
|
+
];
|
|
4624
|
+
const missingFields = requiredFields.filter(({ field }) => !config[field]);
|
|
4625
|
+
if (missingFields.length > 0) {
|
|
4626
|
+
const missing = missingFields.map(({ field, description }) => `${field} (${description})`).join(", ");
|
|
4627
|
+
return `Missing required gasless configuration fields: ${missing}`;
|
|
4628
|
+
}
|
|
4629
|
+
try {
|
|
4630
|
+
new URL(config.relayerUrl);
|
|
4631
|
+
} catch (e) {
|
|
4632
|
+
return `Invalid relayer URL format: ${config.relayerUrl}`;
|
|
4633
|
+
}
|
|
4634
|
+
try {
|
|
4635
|
+
new URL(config.subnetRpcUrl);
|
|
4636
|
+
} catch (e) {
|
|
4637
|
+
return `Invalid subnet RPC URL format: ${config.subnetRpcUrl}`;
|
|
4638
|
+
}
|
|
4639
|
+
if (!config.forwarderAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
|
|
4640
|
+
return `Invalid forwarder address format: ${config.forwarderAddress}. Expected a valid Ethereum address.`;
|
|
4641
|
+
}
|
|
4642
|
+
return null;
|
|
4643
|
+
}
|
|
4644
|
+
var GaslessContext = (0, import_react27.createContext)(null);
|
|
4645
|
+
function GaslessProvider({ children, config, fetchParams }) {
|
|
4646
|
+
const [state, setState] = (0, import_react27.useState)({
|
|
4647
|
+
isLoading: false,
|
|
4648
|
+
error: null,
|
|
4649
|
+
config: null
|
|
4650
|
+
});
|
|
4651
|
+
const { authServiceUrl, environment } = useAvaCloudWallet();
|
|
4652
|
+
(0, import_react27.useEffect)(() => {
|
|
4653
|
+
if (config) {
|
|
4654
|
+
const validationError = validateGaslessConfig(config);
|
|
4655
|
+
if (validationError) {
|
|
4656
|
+
setState({
|
|
4657
|
+
isLoading: false,
|
|
4658
|
+
error: new Error(validationError),
|
|
4659
|
+
config: null
|
|
4660
|
+
});
|
|
4661
|
+
} else {
|
|
4662
|
+
setState({ isLoading: false, error: null, config });
|
|
4663
|
+
}
|
|
4664
|
+
return;
|
|
4665
|
+
}
|
|
4666
|
+
if (!fetchParams) {
|
|
4667
|
+
setState({
|
|
4668
|
+
isLoading: false,
|
|
4669
|
+
error: new Error(
|
|
4670
|
+
"GaslessProvider requires either a `config` prop or `fetchParams` prop. Please provide pre-fetched configuration or parameters to fetch it."
|
|
4671
|
+
),
|
|
4672
|
+
config: null
|
|
4673
|
+
});
|
|
4674
|
+
return;
|
|
4675
|
+
}
|
|
4676
|
+
const { orgId, subnetId } = fetchParams;
|
|
4677
|
+
if (!orgId || !subnetId) {
|
|
4678
|
+
setState({
|
|
4679
|
+
isLoading: false,
|
|
4680
|
+
error: new Error(
|
|
4681
|
+
`Invalid fetchParams: both orgId and subnetId are required. Received: orgId="${orgId}", subnetId="${subnetId}"`
|
|
4682
|
+
),
|
|
4683
|
+
config: null
|
|
4684
|
+
});
|
|
4685
|
+
return;
|
|
4686
|
+
}
|
|
4687
|
+
const fetchConfig = async () => {
|
|
4688
|
+
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
4689
|
+
try {
|
|
4690
|
+
const url = `${authServiceUrl}/api/gasless-config?orgId=${encodeURIComponent(
|
|
4691
|
+
orgId
|
|
4692
|
+
)}&subnetId=${encodeURIComponent(subnetId)}&environment=${environment}`;
|
|
4693
|
+
const resp = await fetch(url);
|
|
4694
|
+
if (!resp.ok) {
|
|
4695
|
+
let errorMessage = `Failed to fetch gasless configuration (HTTP ${resp.status})`;
|
|
4696
|
+
try {
|
|
4697
|
+
const errorData = await resp.json();
|
|
4698
|
+
if (errorData.error) {
|
|
4699
|
+
errorMessage = errorData.error;
|
|
4700
|
+
if (errorData.details) {
|
|
4701
|
+
errorMessage += `: ${errorData.details}`;
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
} catch (e) {
|
|
4705
|
+
if (resp.status === 404) {
|
|
4706
|
+
errorMessage = "Gas relayer configuration not found. Please ensure the gas relayer is set up for your organization and subnet in AvaCloud.";
|
|
4707
|
+
} else if (resp.status === 400) {
|
|
4708
|
+
errorMessage = "Invalid request parameters. Please check your orgId and subnetId.";
|
|
4709
|
+
} else if (resp.status === 500) {
|
|
4710
|
+
errorMessage = "Server error while fetching gasless configuration. Please try again later or contact support.";
|
|
4711
|
+
}
|
|
4712
|
+
}
|
|
4713
|
+
throw new Error(errorMessage);
|
|
4714
|
+
}
|
|
4715
|
+
const cfg = await resp.json();
|
|
4716
|
+
const validationError = validateGaslessConfig(cfg);
|
|
4717
|
+
if (validationError) {
|
|
4718
|
+
throw new Error(
|
|
4719
|
+
`Invalid gasless configuration received from server: ${validationError}. This may indicate an issue with your AvaCloud gas relayer setup.`
|
|
4720
|
+
);
|
|
4721
|
+
}
|
|
4722
|
+
setState({ isLoading: false, error: null, config: cfg });
|
|
4723
|
+
} catch (err) {
|
|
4724
|
+
let error;
|
|
4725
|
+
if (err instanceof Error) {
|
|
4726
|
+
error = err;
|
|
4727
|
+
} else if (err && typeof err === "object" && "message" in err) {
|
|
4728
|
+
error = new Error(String(err.message));
|
|
4729
|
+
} else {
|
|
4730
|
+
error = new Error("An unexpected error occurred while fetching gasless configuration");
|
|
4731
|
+
}
|
|
4732
|
+
setState({ isLoading: false, error, config: null });
|
|
4733
|
+
}
|
|
4734
|
+
};
|
|
4735
|
+
fetchConfig();
|
|
4736
|
+
}, [config, fetchParams, authServiceUrl, environment]);
|
|
4737
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GaslessContext.Provider, { value: state, children });
|
|
4738
|
+
}
|
|
4739
|
+
|
|
4740
|
+
// src/hooks/useGaslessTransaction.ts
|
|
4741
|
+
var import_react28 = require("react");
|
|
4742
|
+
var ethers = __toESM(require("ethers"));
|
|
4743
|
+
var import_axios = __toESM(require("axios"));
|
|
4744
|
+
var import_cubesigner_sdk6 = require("@cubist-labs/cubesigner-sdk");
|
|
4745
|
+
var FORWARDER_GET_NONCE_ABI = [
|
|
4746
|
+
{
|
|
4747
|
+
inputs: [
|
|
4748
|
+
{
|
|
4749
|
+
internalType: "address",
|
|
4750
|
+
name: "from",
|
|
4751
|
+
type: "address"
|
|
4752
|
+
}
|
|
4753
|
+
],
|
|
4754
|
+
name: "getNonce",
|
|
4755
|
+
outputs: [
|
|
4756
|
+
{
|
|
4757
|
+
internalType: "uint256",
|
|
4758
|
+
name: "",
|
|
4759
|
+
type: "uint256"
|
|
4760
|
+
}
|
|
4761
|
+
],
|
|
4762
|
+
stateMutability: "view",
|
|
4763
|
+
type: "function"
|
|
4764
|
+
}
|
|
4765
|
+
];
|
|
4766
|
+
function useGaslessTransaction({ gaslessConfig, contractAddress: defaultContractAddress, abi: defaultAbi }) {
|
|
4767
|
+
const [state, setState] = (0, import_react28.useState)({
|
|
4768
|
+
isLoading: false,
|
|
4769
|
+
error: null,
|
|
4770
|
+
txHash: null
|
|
4771
|
+
});
|
|
4772
|
+
const config = gaslessConfig;
|
|
4773
|
+
const { wallet, cubistClient } = useAvaCloudWallet();
|
|
4774
|
+
useViem();
|
|
4775
|
+
const reset = (0, import_react28.useCallback)(() => {
|
|
4776
|
+
setState({
|
|
4777
|
+
isLoading: false,
|
|
4778
|
+
error: null,
|
|
4779
|
+
txHash: null
|
|
4780
|
+
});
|
|
4781
|
+
}, []);
|
|
4782
|
+
const validateConfig = (0, import_react28.useCallback)((config2) => {
|
|
4783
|
+
if (!config2) {
|
|
4784
|
+
return "Gasless configuration is not available. Please ensure GaslessProvider is properly configured.";
|
|
4785
|
+
}
|
|
4786
|
+
const requiredFields = [
|
|
4787
|
+
{ field: "relayerUrl", description: "Relayer RPC URL" },
|
|
4788
|
+
{ field: "subnetRpcUrl", description: "Subnet RPC URL" },
|
|
4789
|
+
{ field: "forwarderAddress", description: "Forwarder contract address" },
|
|
4790
|
+
{ field: "domainName", description: "EIP-712 domain name" },
|
|
4791
|
+
{ field: "domainVersion", description: "EIP-712 domain version" }
|
|
4792
|
+
];
|
|
4793
|
+
if (!config2.requestType) {
|
|
4794
|
+
config2.requestType = "Message";
|
|
4795
|
+
}
|
|
4796
|
+
for (const { field, description } of requiredFields) {
|
|
4797
|
+
if (!config2[field]) {
|
|
4798
|
+
return `Missing required gasless configuration field: ${field} (${description}). Please check your AvaCloud gas relayer setup.`;
|
|
4799
|
+
}
|
|
4800
|
+
}
|
|
4801
|
+
try {
|
|
4802
|
+
new URL(config2.relayerUrl);
|
|
4803
|
+
} catch (e) {
|
|
4804
|
+
return `Invalid relayer URL: ${config2.relayerUrl}. Expected a valid HTTP/HTTPS URL.`;
|
|
4805
|
+
}
|
|
4806
|
+
try {
|
|
4807
|
+
new URL(config2.subnetRpcUrl);
|
|
4808
|
+
} catch (e) {
|
|
4809
|
+
return `Invalid subnet RPC URL: ${config2.subnetRpcUrl}. Expected a valid HTTP/HTTPS URL.`;
|
|
4810
|
+
}
|
|
4811
|
+
if (!config2.forwarderAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
|
|
4812
|
+
return `Invalid forwarder address: ${config2.forwarderAddress}. Expected a valid Ethereum address.`;
|
|
4813
|
+
}
|
|
4814
|
+
return null;
|
|
4815
|
+
}, []);
|
|
4816
|
+
const sendGaslessTransaction = (0, import_react28.useCallback)(async ({
|
|
4817
|
+
functionName,
|
|
4818
|
+
args = [],
|
|
4819
|
+
abi: overrideAbi,
|
|
4820
|
+
contractAddress: overrideContractAddress
|
|
4821
|
+
}) => {
|
|
4822
|
+
const contractAddress = overrideContractAddress != null ? overrideContractAddress : defaultContractAddress;
|
|
4823
|
+
const abi = overrideAbi != null ? overrideAbi : defaultAbi;
|
|
4824
|
+
if (!contractAddress || !abi) {
|
|
4825
|
+
setState((prev) => ({ ...prev, error: "Contract address and ABI are required. Please provide them either when initializing the hook or when calling sendGaslessTransaction." }));
|
|
4826
|
+
return;
|
|
4827
|
+
}
|
|
4828
|
+
const configError = validateConfig(config);
|
|
4829
|
+
if (configError) {
|
|
4830
|
+
setState((prev) => ({ ...prev, error: configError }));
|
|
4831
|
+
return;
|
|
4832
|
+
}
|
|
4833
|
+
if (!config) {
|
|
4834
|
+
setState((prev) => ({
|
|
4835
|
+
...prev,
|
|
4836
|
+
error: "Gasless configuration is not available. Please ensure you pass a valid config object when initializing useGaslessTransaction."
|
|
4837
|
+
}));
|
|
4838
|
+
return;
|
|
4839
|
+
}
|
|
4840
|
+
if (!(wallet == null ? void 0 : wallet.address)) {
|
|
4841
|
+
setState((prev) => ({ ...prev, error: "Wallet not connected. Please connect your wallet before sending transactions." }));
|
|
4842
|
+
return;
|
|
4843
|
+
}
|
|
4844
|
+
if (!cubistClient) {
|
|
4845
|
+
setState((prev) => ({ ...prev, error: "Authentication client not initialized. Please ensure you are properly authenticated." }));
|
|
4846
|
+
return;
|
|
4847
|
+
}
|
|
4848
|
+
if (!contractAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
|
|
4849
|
+
setState((prev) => ({ ...prev, error: `Invalid contract address: ${contractAddress}. Expected a valid Ethereum address.` }));
|
|
4850
|
+
return;
|
|
4851
|
+
}
|
|
4852
|
+
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
4853
|
+
try {
|
|
4854
|
+
const provider = new ethers.providers.JsonRpcProvider(config.subnetRpcUrl);
|
|
4855
|
+
const forwarder = new ethers.Contract(config.forwarderAddress, FORWARDER_GET_NONCE_ABI, provider);
|
|
4856
|
+
const targetContract = new ethers.Contract(contractAddress, abi, provider);
|
|
4857
|
+
const gas = await targetContract.estimateGas[functionName](...args);
|
|
4858
|
+
const forwarderNonce = await forwarder.getNonce(wallet.address);
|
|
4859
|
+
const data = targetContract.interface.encodeFunctionData(functionName, args);
|
|
4860
|
+
const types = {
|
|
4861
|
+
EIP712Domain: [
|
|
4862
|
+
{ name: "name", type: "string" },
|
|
4863
|
+
{ name: "version", type: "string" },
|
|
4864
|
+
{ name: "chainId", type: "uint256" },
|
|
4865
|
+
{ name: "verifyingContract", type: "address" }
|
|
4866
|
+
],
|
|
4867
|
+
[config.requestType]: [
|
|
4868
|
+
{ name: "from", type: "address" },
|
|
4869
|
+
{ name: "to", type: "address" },
|
|
4870
|
+
{ name: "value", type: "uint256" },
|
|
4871
|
+
{ name: "gas", type: "uint256" },
|
|
4872
|
+
{ name: "nonce", type: "uint256" },
|
|
4873
|
+
{ name: "data", type: "bytes" },
|
|
4874
|
+
{ name: "validUntilTime", type: "uint256" }
|
|
4875
|
+
]
|
|
4876
|
+
};
|
|
4877
|
+
if (config.suffix) {
|
|
4878
|
+
const suffixParts = config.suffix.match(/^(\w+)\s+(.+)\)$/);
|
|
4879
|
+
if (suffixParts) {
|
|
4880
|
+
const [, suffixType, suffixName] = suffixParts;
|
|
4881
|
+
types[config.requestType].push({
|
|
4882
|
+
name: suffixName,
|
|
4883
|
+
type: suffixType
|
|
4884
|
+
});
|
|
4885
|
+
}
|
|
4886
|
+
}
|
|
4887
|
+
const nonceHex = forwarderNonce.toHexString();
|
|
4888
|
+
const message = {
|
|
4889
|
+
from: wallet.address,
|
|
4890
|
+
to: contractAddress,
|
|
4891
|
+
value: "0x0",
|
|
4892
|
+
gas: gas.toHexString(),
|
|
4893
|
+
nonce: nonceHex,
|
|
4894
|
+
data,
|
|
4895
|
+
validUntilTime: "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
|
4896
|
+
};
|
|
4897
|
+
if (config.suffix) {
|
|
4898
|
+
const suffixParts = config.suffix.match(/^(\w+)\s+(.+)\)$/);
|
|
4899
|
+
if (suffixParts) {
|
|
4900
|
+
const [, , suffixName] = suffixParts;
|
|
4901
|
+
message[suffixName] = Buffer.from(config.suffix, "utf8");
|
|
4902
|
+
}
|
|
4903
|
+
}
|
|
4904
|
+
const domain = {
|
|
4905
|
+
name: config.domainName,
|
|
4906
|
+
version: config.domainVersion,
|
|
4907
|
+
chainId: (await provider.getNetwork()).chainId,
|
|
4908
|
+
verifyingContract: config.forwarderAddress
|
|
4909
|
+
};
|
|
4910
|
+
const digest = ethers.utils._TypedDataEncoder.hash(domain, {
|
|
4911
|
+
[config.requestType]: types[config.requestType]
|
|
4912
|
+
}, message);
|
|
4913
|
+
const key = await cubistClient.org().getKeyByMaterialId(import_cubesigner_sdk6.Secp256k1.Evm, wallet.address);
|
|
4914
|
+
const sigResp = await key.signBlob({
|
|
4915
|
+
message_base64: Buffer.from(digest.slice(2), "hex").toString("base64")
|
|
4916
|
+
});
|
|
4917
|
+
const signatureData = sigResp.data().signature;
|
|
4918
|
+
const signature = signatureData.startsWith("0x") ? signatureData : `0x${signatureData}`;
|
|
4919
|
+
const typedRequest = {
|
|
4920
|
+
domain,
|
|
4921
|
+
types: {
|
|
4922
|
+
[config.requestType]: types[config.requestType]
|
|
4923
|
+
},
|
|
4924
|
+
primaryType: config.requestType,
|
|
4925
|
+
message
|
|
4926
|
+
};
|
|
4927
|
+
const txPayload = {
|
|
4928
|
+
forwardRequest: typedRequest,
|
|
4929
|
+
metadata: {
|
|
4930
|
+
signature: signature.substring(2)
|
|
4931
|
+
// strip 0x
|
|
4932
|
+
}
|
|
4933
|
+
};
|
|
4934
|
+
const rawTx = "0x" + Buffer.from(JSON.stringify(txPayload), "utf8").toString("hex");
|
|
4935
|
+
const requestBody = {
|
|
4936
|
+
id: 1,
|
|
4937
|
+
jsonrpc: "2.0",
|
|
4938
|
+
method: "eth_sendRawTransaction",
|
|
4939
|
+
params: [rawTx]
|
|
4940
|
+
};
|
|
4941
|
+
const resp = await import_axios.default.post(config.relayerUrl, requestBody, {
|
|
4942
|
+
headers: {
|
|
4943
|
+
"Content-Type": "application/json"
|
|
4944
|
+
}
|
|
4945
|
+
});
|
|
4946
|
+
const txHash = resp.data.result;
|
|
4947
|
+
setState((prev) => ({ ...prev, txHash }));
|
|
4948
|
+
await provider.waitForTransaction(txHash);
|
|
4949
|
+
} catch (err) {
|
|
4950
|
+
let errorMessage = "Failed to send gasless transaction";
|
|
4951
|
+
if (err instanceof Error) {
|
|
4952
|
+
if (err.message.includes("estimateGas")) {
|
|
4953
|
+
errorMessage = `Failed to estimate gas for function "${functionName}". Please verify the function exists and parameters are correct.`;
|
|
4954
|
+
} else if (err.message.includes("getNonce")) {
|
|
4955
|
+
errorMessage = "Failed to fetch nonce from forwarder contract. Please verify the forwarder address is correct and deployed.";
|
|
4956
|
+
} else if (err.message.includes("getKeyByMaterialId")) {
|
|
4957
|
+
errorMessage = "Failed to retrieve signing key. Please ensure your wallet is properly initialized.";
|
|
4958
|
+
} else if (err.message.includes("signBlob")) {
|
|
4959
|
+
errorMessage = "Failed to sign transaction. Please check your authentication status.";
|
|
4960
|
+
} else if (err.message.includes("Network Error") || err.message.includes("ECONNREFUSED")) {
|
|
4961
|
+
errorMessage = "Network error: Unable to connect to relayer service. Please check your internet connection and relayer URL.";
|
|
4962
|
+
} else if (err.message.includes("404")) {
|
|
4963
|
+
errorMessage = "Relayer endpoint not found. Please verify the relayer URL is correct.";
|
|
4964
|
+
} else if (err.message.includes("500") || err.message.includes("502") || err.message.includes("503")) {
|
|
4965
|
+
errorMessage = "Relayer service error. The gas relayer service may be temporarily unavailable.";
|
|
4966
|
+
} else if (err.message.includes("insufficient funds")) {
|
|
4967
|
+
errorMessage = "The relayer has insufficient funds to sponsor this transaction. Please contact support.";
|
|
4968
|
+
} else {
|
|
4969
|
+
errorMessage = `Transaction failed: ${err.message}`;
|
|
4970
|
+
}
|
|
4971
|
+
}
|
|
4972
|
+
setState((prev) => ({
|
|
4973
|
+
...prev,
|
|
4974
|
+
error: errorMessage
|
|
4975
|
+
}));
|
|
4976
|
+
} finally {
|
|
4977
|
+
setState((prev) => ({ ...prev, isLoading: false }));
|
|
4978
|
+
}
|
|
4979
|
+
}, [config, wallet == null ? void 0 : wallet.address, cubistClient, validateConfig, defaultAbi, defaultContractAddress]);
|
|
4980
|
+
return {
|
|
4981
|
+
...state,
|
|
4982
|
+
sendGaslessTransaction,
|
|
4983
|
+
reset
|
|
4984
|
+
};
|
|
4985
|
+
}
|
|
4590
4986
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4591
4987
|
0 && (module.exports = {
|
|
4592
4988
|
AvaCloudWalletProvider,
|
|
4593
4989
|
ExportView,
|
|
4990
|
+
GaslessProvider,
|
|
4594
4991
|
LoginButton,
|
|
4595
4992
|
ReceiveView,
|
|
4596
4993
|
SendView,
|
|
@@ -4604,7 +5001,10 @@ function avaCloudWallet() {
|
|
|
4604
5001
|
avaCloudWallet,
|
|
4605
5002
|
useAuth,
|
|
4606
5003
|
useAvaCloudWallet,
|
|
5004
|
+
useBlockchain,
|
|
4607
5005
|
useChainId,
|
|
5006
|
+
useGaslessTransaction,
|
|
5007
|
+
useGlacier,
|
|
4608
5008
|
usePostMessage,
|
|
4609
5009
|
useSignMessage,
|
|
4610
5010
|
useSignTransaction,
|
package/dist/index.mjs
CHANGED
|
@@ -1581,6 +1581,10 @@ function AvaCloudWalletProvider({
|
|
|
1581
1581
|
onAuthError,
|
|
1582
1582
|
onWalletUpdate
|
|
1583
1583
|
}) {
|
|
1584
|
+
const { setChainId } = useChainId();
|
|
1585
|
+
useEffect5(() => {
|
|
1586
|
+
setChainId(chainId);
|
|
1587
|
+
}, [chainId, setChainId]);
|
|
1584
1588
|
const authServiceUrl = env === "development" ? "http://localhost:3000" : env === "staging" ? "https://ac-auth-service-env-staging-ava-labs.vercel.app" : "https://ac-auth-service.vercel.app";
|
|
1585
1589
|
const environment = env;
|
|
1586
1590
|
const [isAuthenticated, setIsAuthenticated] = useState7(false);
|
|
@@ -4622,9 +4626,388 @@ function avaCloudWallet() {
|
|
|
4622
4626
|
}
|
|
4623
4627
|
}));
|
|
4624
4628
|
}
|
|
4629
|
+
|
|
4630
|
+
// src/providers/GaslessProvider.tsx
|
|
4631
|
+
import { createContext as createContext5, useContext as useContext5, useEffect as useEffect7, useState as useState21 } from "react";
|
|
4632
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
4633
|
+
function validateGaslessConfig(config) {
|
|
4634
|
+
if (!config || typeof config !== "object") {
|
|
4635
|
+
return "Invalid gasless configuration: expected an object";
|
|
4636
|
+
}
|
|
4637
|
+
const requiredFields = [
|
|
4638
|
+
{ field: "relayerUrl", description: "Relayer RPC URL" },
|
|
4639
|
+
{ field: "subnetRpcUrl", description: "Subnet RPC URL" },
|
|
4640
|
+
{ field: "forwarderAddress", description: "Forwarder contract address" },
|
|
4641
|
+
{ field: "domainName", description: "EIP-712 domain name" },
|
|
4642
|
+
{ field: "domainVersion", description: "EIP-712 domain version" },
|
|
4643
|
+
{ field: "requestType", description: "Request type name" }
|
|
4644
|
+
];
|
|
4645
|
+
const missingFields = requiredFields.filter(({ field }) => !config[field]);
|
|
4646
|
+
if (missingFields.length > 0) {
|
|
4647
|
+
const missing = missingFields.map(({ field, description }) => `${field} (${description})`).join(", ");
|
|
4648
|
+
return `Missing required gasless configuration fields: ${missing}`;
|
|
4649
|
+
}
|
|
4650
|
+
try {
|
|
4651
|
+
new URL(config.relayerUrl);
|
|
4652
|
+
} catch (e) {
|
|
4653
|
+
return `Invalid relayer URL format: ${config.relayerUrl}`;
|
|
4654
|
+
}
|
|
4655
|
+
try {
|
|
4656
|
+
new URL(config.subnetRpcUrl);
|
|
4657
|
+
} catch (e) {
|
|
4658
|
+
return `Invalid subnet RPC URL format: ${config.subnetRpcUrl}`;
|
|
4659
|
+
}
|
|
4660
|
+
if (!config.forwarderAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
|
|
4661
|
+
return `Invalid forwarder address format: ${config.forwarderAddress}. Expected a valid Ethereum address.`;
|
|
4662
|
+
}
|
|
4663
|
+
return null;
|
|
4664
|
+
}
|
|
4665
|
+
var GaslessContext = createContext5(null);
|
|
4666
|
+
function GaslessProvider({ children, config, fetchParams }) {
|
|
4667
|
+
const [state, setState] = useState21({
|
|
4668
|
+
isLoading: false,
|
|
4669
|
+
error: null,
|
|
4670
|
+
config: null
|
|
4671
|
+
});
|
|
4672
|
+
const { authServiceUrl, environment } = useAvaCloudWallet();
|
|
4673
|
+
useEffect7(() => {
|
|
4674
|
+
if (config) {
|
|
4675
|
+
const validationError = validateGaslessConfig(config);
|
|
4676
|
+
if (validationError) {
|
|
4677
|
+
setState({
|
|
4678
|
+
isLoading: false,
|
|
4679
|
+
error: new Error(validationError),
|
|
4680
|
+
config: null
|
|
4681
|
+
});
|
|
4682
|
+
} else {
|
|
4683
|
+
setState({ isLoading: false, error: null, config });
|
|
4684
|
+
}
|
|
4685
|
+
return;
|
|
4686
|
+
}
|
|
4687
|
+
if (!fetchParams) {
|
|
4688
|
+
setState({
|
|
4689
|
+
isLoading: false,
|
|
4690
|
+
error: new Error(
|
|
4691
|
+
"GaslessProvider requires either a `config` prop or `fetchParams` prop. Please provide pre-fetched configuration or parameters to fetch it."
|
|
4692
|
+
),
|
|
4693
|
+
config: null
|
|
4694
|
+
});
|
|
4695
|
+
return;
|
|
4696
|
+
}
|
|
4697
|
+
const { orgId, subnetId } = fetchParams;
|
|
4698
|
+
if (!orgId || !subnetId) {
|
|
4699
|
+
setState({
|
|
4700
|
+
isLoading: false,
|
|
4701
|
+
error: new Error(
|
|
4702
|
+
`Invalid fetchParams: both orgId and subnetId are required. Received: orgId="${orgId}", subnetId="${subnetId}"`
|
|
4703
|
+
),
|
|
4704
|
+
config: null
|
|
4705
|
+
});
|
|
4706
|
+
return;
|
|
4707
|
+
}
|
|
4708
|
+
const fetchConfig = async () => {
|
|
4709
|
+
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
4710
|
+
try {
|
|
4711
|
+
const url = `${authServiceUrl}/api/gasless-config?orgId=${encodeURIComponent(
|
|
4712
|
+
orgId
|
|
4713
|
+
)}&subnetId=${encodeURIComponent(subnetId)}&environment=${environment}`;
|
|
4714
|
+
const resp = await fetch(url);
|
|
4715
|
+
if (!resp.ok) {
|
|
4716
|
+
let errorMessage = `Failed to fetch gasless configuration (HTTP ${resp.status})`;
|
|
4717
|
+
try {
|
|
4718
|
+
const errorData = await resp.json();
|
|
4719
|
+
if (errorData.error) {
|
|
4720
|
+
errorMessage = errorData.error;
|
|
4721
|
+
if (errorData.details) {
|
|
4722
|
+
errorMessage += `: ${errorData.details}`;
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
} catch (e) {
|
|
4726
|
+
if (resp.status === 404) {
|
|
4727
|
+
errorMessage = "Gas relayer configuration not found. Please ensure the gas relayer is set up for your organization and subnet in AvaCloud.";
|
|
4728
|
+
} else if (resp.status === 400) {
|
|
4729
|
+
errorMessage = "Invalid request parameters. Please check your orgId and subnetId.";
|
|
4730
|
+
} else if (resp.status === 500) {
|
|
4731
|
+
errorMessage = "Server error while fetching gasless configuration. Please try again later or contact support.";
|
|
4732
|
+
}
|
|
4733
|
+
}
|
|
4734
|
+
throw new Error(errorMessage);
|
|
4735
|
+
}
|
|
4736
|
+
const cfg = await resp.json();
|
|
4737
|
+
const validationError = validateGaslessConfig(cfg);
|
|
4738
|
+
if (validationError) {
|
|
4739
|
+
throw new Error(
|
|
4740
|
+
`Invalid gasless configuration received from server: ${validationError}. This may indicate an issue with your AvaCloud gas relayer setup.`
|
|
4741
|
+
);
|
|
4742
|
+
}
|
|
4743
|
+
setState({ isLoading: false, error: null, config: cfg });
|
|
4744
|
+
} catch (err) {
|
|
4745
|
+
let error;
|
|
4746
|
+
if (err instanceof Error) {
|
|
4747
|
+
error = err;
|
|
4748
|
+
} else if (err && typeof err === "object" && "message" in err) {
|
|
4749
|
+
error = new Error(String(err.message));
|
|
4750
|
+
} else {
|
|
4751
|
+
error = new Error("An unexpected error occurred while fetching gasless configuration");
|
|
4752
|
+
}
|
|
4753
|
+
setState({ isLoading: false, error, config: null });
|
|
4754
|
+
}
|
|
4755
|
+
};
|
|
4756
|
+
fetchConfig();
|
|
4757
|
+
}, [config, fetchParams, authServiceUrl, environment]);
|
|
4758
|
+
return /* @__PURE__ */ jsx24(GaslessContext.Provider, { value: state, children });
|
|
4759
|
+
}
|
|
4760
|
+
|
|
4761
|
+
// src/hooks/useGaslessTransaction.ts
|
|
4762
|
+
import { useCallback as useCallback11, useState as useState22 } from "react";
|
|
4763
|
+
import * as ethers from "ethers";
|
|
4764
|
+
import axios from "axios";
|
|
4765
|
+
import { Secp256k1 as Secp256k14 } from "@cubist-labs/cubesigner-sdk";
|
|
4766
|
+
var FORWARDER_GET_NONCE_ABI = [
|
|
4767
|
+
{
|
|
4768
|
+
inputs: [
|
|
4769
|
+
{
|
|
4770
|
+
internalType: "address",
|
|
4771
|
+
name: "from",
|
|
4772
|
+
type: "address"
|
|
4773
|
+
}
|
|
4774
|
+
],
|
|
4775
|
+
name: "getNonce",
|
|
4776
|
+
outputs: [
|
|
4777
|
+
{
|
|
4778
|
+
internalType: "uint256",
|
|
4779
|
+
name: "",
|
|
4780
|
+
type: "uint256"
|
|
4781
|
+
}
|
|
4782
|
+
],
|
|
4783
|
+
stateMutability: "view",
|
|
4784
|
+
type: "function"
|
|
4785
|
+
}
|
|
4786
|
+
];
|
|
4787
|
+
function useGaslessTransaction({ gaslessConfig, contractAddress: defaultContractAddress, abi: defaultAbi }) {
|
|
4788
|
+
const [state, setState] = useState22({
|
|
4789
|
+
isLoading: false,
|
|
4790
|
+
error: null,
|
|
4791
|
+
txHash: null
|
|
4792
|
+
});
|
|
4793
|
+
const config = gaslessConfig;
|
|
4794
|
+
const { wallet, cubistClient } = useAvaCloudWallet();
|
|
4795
|
+
useViem();
|
|
4796
|
+
const reset = useCallback11(() => {
|
|
4797
|
+
setState({
|
|
4798
|
+
isLoading: false,
|
|
4799
|
+
error: null,
|
|
4800
|
+
txHash: null
|
|
4801
|
+
});
|
|
4802
|
+
}, []);
|
|
4803
|
+
const validateConfig = useCallback11((config2) => {
|
|
4804
|
+
if (!config2) {
|
|
4805
|
+
return "Gasless configuration is not available. Please ensure GaslessProvider is properly configured.";
|
|
4806
|
+
}
|
|
4807
|
+
const requiredFields = [
|
|
4808
|
+
{ field: "relayerUrl", description: "Relayer RPC URL" },
|
|
4809
|
+
{ field: "subnetRpcUrl", description: "Subnet RPC URL" },
|
|
4810
|
+
{ field: "forwarderAddress", description: "Forwarder contract address" },
|
|
4811
|
+
{ field: "domainName", description: "EIP-712 domain name" },
|
|
4812
|
+
{ field: "domainVersion", description: "EIP-712 domain version" }
|
|
4813
|
+
];
|
|
4814
|
+
if (!config2.requestType) {
|
|
4815
|
+
config2.requestType = "Message";
|
|
4816
|
+
}
|
|
4817
|
+
for (const { field, description } of requiredFields) {
|
|
4818
|
+
if (!config2[field]) {
|
|
4819
|
+
return `Missing required gasless configuration field: ${field} (${description}). Please check your AvaCloud gas relayer setup.`;
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
try {
|
|
4823
|
+
new URL(config2.relayerUrl);
|
|
4824
|
+
} catch (e) {
|
|
4825
|
+
return `Invalid relayer URL: ${config2.relayerUrl}. Expected a valid HTTP/HTTPS URL.`;
|
|
4826
|
+
}
|
|
4827
|
+
try {
|
|
4828
|
+
new URL(config2.subnetRpcUrl);
|
|
4829
|
+
} catch (e) {
|
|
4830
|
+
return `Invalid subnet RPC URL: ${config2.subnetRpcUrl}. Expected a valid HTTP/HTTPS URL.`;
|
|
4831
|
+
}
|
|
4832
|
+
if (!config2.forwarderAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
|
|
4833
|
+
return `Invalid forwarder address: ${config2.forwarderAddress}. Expected a valid Ethereum address.`;
|
|
4834
|
+
}
|
|
4835
|
+
return null;
|
|
4836
|
+
}, []);
|
|
4837
|
+
const sendGaslessTransaction = useCallback11(async ({
|
|
4838
|
+
functionName,
|
|
4839
|
+
args = [],
|
|
4840
|
+
abi: overrideAbi,
|
|
4841
|
+
contractAddress: overrideContractAddress
|
|
4842
|
+
}) => {
|
|
4843
|
+
const contractAddress = overrideContractAddress != null ? overrideContractAddress : defaultContractAddress;
|
|
4844
|
+
const abi = overrideAbi != null ? overrideAbi : defaultAbi;
|
|
4845
|
+
if (!contractAddress || !abi) {
|
|
4846
|
+
setState((prev) => ({ ...prev, error: "Contract address and ABI are required. Please provide them either when initializing the hook or when calling sendGaslessTransaction." }));
|
|
4847
|
+
return;
|
|
4848
|
+
}
|
|
4849
|
+
const configError = validateConfig(config);
|
|
4850
|
+
if (configError) {
|
|
4851
|
+
setState((prev) => ({ ...prev, error: configError }));
|
|
4852
|
+
return;
|
|
4853
|
+
}
|
|
4854
|
+
if (!config) {
|
|
4855
|
+
setState((prev) => ({
|
|
4856
|
+
...prev,
|
|
4857
|
+
error: "Gasless configuration is not available. Please ensure you pass a valid config object when initializing useGaslessTransaction."
|
|
4858
|
+
}));
|
|
4859
|
+
return;
|
|
4860
|
+
}
|
|
4861
|
+
if (!(wallet == null ? void 0 : wallet.address)) {
|
|
4862
|
+
setState((prev) => ({ ...prev, error: "Wallet not connected. Please connect your wallet before sending transactions." }));
|
|
4863
|
+
return;
|
|
4864
|
+
}
|
|
4865
|
+
if (!cubistClient) {
|
|
4866
|
+
setState((prev) => ({ ...prev, error: "Authentication client not initialized. Please ensure you are properly authenticated." }));
|
|
4867
|
+
return;
|
|
4868
|
+
}
|
|
4869
|
+
if (!contractAddress.match(/^0x[a-fA-F0-9]{40}$/)) {
|
|
4870
|
+
setState((prev) => ({ ...prev, error: `Invalid contract address: ${contractAddress}. Expected a valid Ethereum address.` }));
|
|
4871
|
+
return;
|
|
4872
|
+
}
|
|
4873
|
+
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
4874
|
+
try {
|
|
4875
|
+
const provider = new ethers.providers.JsonRpcProvider(config.subnetRpcUrl);
|
|
4876
|
+
const forwarder = new ethers.Contract(config.forwarderAddress, FORWARDER_GET_NONCE_ABI, provider);
|
|
4877
|
+
const targetContract = new ethers.Contract(contractAddress, abi, provider);
|
|
4878
|
+
const gas = await targetContract.estimateGas[functionName](...args);
|
|
4879
|
+
const forwarderNonce = await forwarder.getNonce(wallet.address);
|
|
4880
|
+
const data = targetContract.interface.encodeFunctionData(functionName, args);
|
|
4881
|
+
const types = {
|
|
4882
|
+
EIP712Domain: [
|
|
4883
|
+
{ name: "name", type: "string" },
|
|
4884
|
+
{ name: "version", type: "string" },
|
|
4885
|
+
{ name: "chainId", type: "uint256" },
|
|
4886
|
+
{ name: "verifyingContract", type: "address" }
|
|
4887
|
+
],
|
|
4888
|
+
[config.requestType]: [
|
|
4889
|
+
{ name: "from", type: "address" },
|
|
4890
|
+
{ name: "to", type: "address" },
|
|
4891
|
+
{ name: "value", type: "uint256" },
|
|
4892
|
+
{ name: "gas", type: "uint256" },
|
|
4893
|
+
{ name: "nonce", type: "uint256" },
|
|
4894
|
+
{ name: "data", type: "bytes" },
|
|
4895
|
+
{ name: "validUntilTime", type: "uint256" }
|
|
4896
|
+
]
|
|
4897
|
+
};
|
|
4898
|
+
if (config.suffix) {
|
|
4899
|
+
const suffixParts = config.suffix.match(/^(\w+)\s+(.+)\)$/);
|
|
4900
|
+
if (suffixParts) {
|
|
4901
|
+
const [, suffixType, suffixName] = suffixParts;
|
|
4902
|
+
types[config.requestType].push({
|
|
4903
|
+
name: suffixName,
|
|
4904
|
+
type: suffixType
|
|
4905
|
+
});
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
const nonceHex = forwarderNonce.toHexString();
|
|
4909
|
+
const message = {
|
|
4910
|
+
from: wallet.address,
|
|
4911
|
+
to: contractAddress,
|
|
4912
|
+
value: "0x0",
|
|
4913
|
+
gas: gas.toHexString(),
|
|
4914
|
+
nonce: nonceHex,
|
|
4915
|
+
data,
|
|
4916
|
+
validUntilTime: "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
|
4917
|
+
};
|
|
4918
|
+
if (config.suffix) {
|
|
4919
|
+
const suffixParts = config.suffix.match(/^(\w+)\s+(.+)\)$/);
|
|
4920
|
+
if (suffixParts) {
|
|
4921
|
+
const [, , suffixName] = suffixParts;
|
|
4922
|
+
message[suffixName] = Buffer.from(config.suffix, "utf8");
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
const domain = {
|
|
4926
|
+
name: config.domainName,
|
|
4927
|
+
version: config.domainVersion,
|
|
4928
|
+
chainId: (await provider.getNetwork()).chainId,
|
|
4929
|
+
verifyingContract: config.forwarderAddress
|
|
4930
|
+
};
|
|
4931
|
+
const digest = ethers.utils._TypedDataEncoder.hash(domain, {
|
|
4932
|
+
[config.requestType]: types[config.requestType]
|
|
4933
|
+
}, message);
|
|
4934
|
+
const key = await cubistClient.org().getKeyByMaterialId(Secp256k14.Evm, wallet.address);
|
|
4935
|
+
const sigResp = await key.signBlob({
|
|
4936
|
+
message_base64: Buffer.from(digest.slice(2), "hex").toString("base64")
|
|
4937
|
+
});
|
|
4938
|
+
const signatureData = sigResp.data().signature;
|
|
4939
|
+
const signature = signatureData.startsWith("0x") ? signatureData : `0x${signatureData}`;
|
|
4940
|
+
const typedRequest = {
|
|
4941
|
+
domain,
|
|
4942
|
+
types: {
|
|
4943
|
+
[config.requestType]: types[config.requestType]
|
|
4944
|
+
},
|
|
4945
|
+
primaryType: config.requestType,
|
|
4946
|
+
message
|
|
4947
|
+
};
|
|
4948
|
+
const txPayload = {
|
|
4949
|
+
forwardRequest: typedRequest,
|
|
4950
|
+
metadata: {
|
|
4951
|
+
signature: signature.substring(2)
|
|
4952
|
+
// strip 0x
|
|
4953
|
+
}
|
|
4954
|
+
};
|
|
4955
|
+
const rawTx = "0x" + Buffer.from(JSON.stringify(txPayload), "utf8").toString("hex");
|
|
4956
|
+
const requestBody = {
|
|
4957
|
+
id: 1,
|
|
4958
|
+
jsonrpc: "2.0",
|
|
4959
|
+
method: "eth_sendRawTransaction",
|
|
4960
|
+
params: [rawTx]
|
|
4961
|
+
};
|
|
4962
|
+
const resp = await axios.post(config.relayerUrl, requestBody, {
|
|
4963
|
+
headers: {
|
|
4964
|
+
"Content-Type": "application/json"
|
|
4965
|
+
}
|
|
4966
|
+
});
|
|
4967
|
+
const txHash = resp.data.result;
|
|
4968
|
+
setState((prev) => ({ ...prev, txHash }));
|
|
4969
|
+
await provider.waitForTransaction(txHash);
|
|
4970
|
+
} catch (err) {
|
|
4971
|
+
let errorMessage = "Failed to send gasless transaction";
|
|
4972
|
+
if (err instanceof Error) {
|
|
4973
|
+
if (err.message.includes("estimateGas")) {
|
|
4974
|
+
errorMessage = `Failed to estimate gas for function "${functionName}". Please verify the function exists and parameters are correct.`;
|
|
4975
|
+
} else if (err.message.includes("getNonce")) {
|
|
4976
|
+
errorMessage = "Failed to fetch nonce from forwarder contract. Please verify the forwarder address is correct and deployed.";
|
|
4977
|
+
} else if (err.message.includes("getKeyByMaterialId")) {
|
|
4978
|
+
errorMessage = "Failed to retrieve signing key. Please ensure your wallet is properly initialized.";
|
|
4979
|
+
} else if (err.message.includes("signBlob")) {
|
|
4980
|
+
errorMessage = "Failed to sign transaction. Please check your authentication status.";
|
|
4981
|
+
} else if (err.message.includes("Network Error") || err.message.includes("ECONNREFUSED")) {
|
|
4982
|
+
errorMessage = "Network error: Unable to connect to relayer service. Please check your internet connection and relayer URL.";
|
|
4983
|
+
} else if (err.message.includes("404")) {
|
|
4984
|
+
errorMessage = "Relayer endpoint not found. Please verify the relayer URL is correct.";
|
|
4985
|
+
} else if (err.message.includes("500") || err.message.includes("502") || err.message.includes("503")) {
|
|
4986
|
+
errorMessage = "Relayer service error. The gas relayer service may be temporarily unavailable.";
|
|
4987
|
+
} else if (err.message.includes("insufficient funds")) {
|
|
4988
|
+
errorMessage = "The relayer has insufficient funds to sponsor this transaction. Please contact support.";
|
|
4989
|
+
} else {
|
|
4990
|
+
errorMessage = `Transaction failed: ${err.message}`;
|
|
4991
|
+
}
|
|
4992
|
+
}
|
|
4993
|
+
setState((prev) => ({
|
|
4994
|
+
...prev,
|
|
4995
|
+
error: errorMessage
|
|
4996
|
+
}));
|
|
4997
|
+
} finally {
|
|
4998
|
+
setState((prev) => ({ ...prev, isLoading: false }));
|
|
4999
|
+
}
|
|
5000
|
+
}, [config, wallet == null ? void 0 : wallet.address, cubistClient, validateConfig, defaultAbi, defaultContractAddress]);
|
|
5001
|
+
return {
|
|
5002
|
+
...state,
|
|
5003
|
+
sendGaslessTransaction,
|
|
5004
|
+
reset
|
|
5005
|
+
};
|
|
5006
|
+
}
|
|
4625
5007
|
export {
|
|
4626
5008
|
AvaCloudWalletProvider,
|
|
4627
5009
|
ExportView,
|
|
5010
|
+
GaslessProvider,
|
|
4628
5011
|
LoginButton,
|
|
4629
5012
|
ReceiveView,
|
|
4630
5013
|
SendView,
|
|
@@ -4638,7 +5021,10 @@ export {
|
|
|
4638
5021
|
avaCloudWallet,
|
|
4639
5022
|
useAuth,
|
|
4640
5023
|
useAvaCloudWallet,
|
|
5024
|
+
useBlockchain,
|
|
4641
5025
|
useChainId,
|
|
5026
|
+
useGaslessTransaction,
|
|
5027
|
+
useGlacier,
|
|
4642
5028
|
usePostMessage,
|
|
4643
5029
|
useSignMessage,
|
|
4644
5030
|
useSignTransaction,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@avalabs/avacloud-waas-react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14-nightly.20250704",
|
|
4
4
|
"description": "React SDK for AvaCloud Wallet as a Service",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -10,8 +10,16 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"dist/**"
|
|
12
12
|
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --external react && cp -r public/* dist/",
|
|
15
|
+
"dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react",
|
|
16
|
+
"lint": "eslint \"src/**/*.ts*\"",
|
|
17
|
+
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
13
20
|
"devDependencies": {
|
|
14
21
|
"@iconify/types": "^2.0.0",
|
|
22
|
+
"@types/node": "^20.9.0",
|
|
15
23
|
"@types/react": "^18.2.46",
|
|
16
24
|
"@types/react-dom": "^18.2.18",
|
|
17
25
|
"eslint": "^8.53.0",
|
|
@@ -31,7 +39,9 @@
|
|
|
31
39
|
"@wagmi/core": "^2.17.3",
|
|
32
40
|
"lottie-react": "^2.4.0",
|
|
33
41
|
"qrcode.react": "^3.1.0",
|
|
34
|
-
"viem": "2.31.2"
|
|
42
|
+
"viem": "2.31.2",
|
|
43
|
+
"ethers": "^5.7.2",
|
|
44
|
+
"axios": "^1.6.0"
|
|
35
45
|
},
|
|
36
46
|
"keywords": [
|
|
37
47
|
"avalanche",
|
|
@@ -50,11 +60,5 @@
|
|
|
50
60
|
"url": "https://github.com/ava-labs/avacloud-auth-react/issues"
|
|
51
61
|
},
|
|
52
62
|
"homepage": "https://github.com/ava-labs/avacloud-auth-react#readme",
|
|
53
|
-
"author": "Ava Labs, Inc."
|
|
54
|
-
|
|
55
|
-
"build": "tsup src/index.ts --format esm,cjs --dts --external react && cp -r public/* dist/",
|
|
56
|
-
"dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react",
|
|
57
|
-
"lint": "eslint \"src/**/*.ts*\"",
|
|
58
|
-
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
63
|
+
"author": "Ava Labs, Inc."
|
|
64
|
+
}
|