diff --git a/es/sdk/web/wallet-sdk/ecosystem/getting-started.mdx b/es/sdk/web/wallet-sdk/ecosystem/getting-started.mdx index e74cc947..fd47ce66 100644 --- a/es/sdk/web/wallet-sdk/ecosystem/getting-started.mdx +++ b/es/sdk/web/wallet-sdk/ecosystem/getting-started.mdx @@ -15,11 +15,11 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t ```bash - npm install @0xsequence/connect@v6-beta wagmi viem + npm install @0xsequence/connect@v6-beta wagmi viem # or - pnpm install @0xsequence/connect@v6-beta wagmi viem + pnpm install @0xsequence/connect@v6-beta wagmi viem # or - yarn add @0xsequence/connect@v6-beta wagmi viem + yarn add @0xsequence/connect@v6-beta wagmi viem ``` @@ -36,17 +36,17 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t - `dappOrigin` - `signIn.projectName`, `appName` - `chainIds`, `defaultChainId` - - `explicitSessionParams` (opcional; `nativeTokenSpending` por defecto es `valueLimit: 0`) + - `explicitSession` (opcional; solicita permisos y límites explícitos de sesión) - `includeFeeOptionPermissions`, `enableImplicitSession` - `nodesUrl`, `relayerUrl` - `walletConnect` ```typescript [config.ts] - import { createConfig } from "@0xsequence/connect"; + import { createConfig, createExplicitSession } from "@0xsequence/connect"; export const config: any = createConfig({ projectAccessKey: "AQAAAAAAAABtDHG1It7lxRF_9bbxw4diip8", - walletUrl: 'https://next-acme-wallet.sequence-dev.app', + walletUrl: 'https://acme-wallet.ecosystem-demo.xyz', // Optional dappOrigin: window.location.origin, signIn: { @@ -58,18 +58,29 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t google: true, apple: true, email: true, - explicitSessionParams: { ... } + explicitSession: createExplicitSession({ ... }) }); ``` - El `walletUrl` es la URL del Ecosystem Wallet que su dApp usará. Para nuestra demo, estamos usando el [Acme Ecosystem Wallet](https://next-acme-wallet.sequence-dev.app). + El `walletUrl` es la URL del Ecosystem Wallet que su dApp utilizará. Para nuestra demostración, estamos usando el [Acme Ecosystem Wallet](https://acme-wallet.ecosystem-demo.xyz). El `dappOrigin` es el origen de su dapp, usado para verificar de dónde proviene el usuario. - El objeto `explicitSessionParams` permite que su dapp solicite permisos específicos al usuario al conectarse. - Estos permisos pueden autorizar a su dapp a realizar ciertas acciones en nombre del usuario durante un período definido, creando una experiencia más fluida sin solicitudes de transacción o permitiendo automatizaciones. + El objeto `explicitSession` permite que su dapp solicite permisos específicos al usuario al conectarse. + Estos permisos pueden autorizar a su dapp a realizar ciertas acciones en nombre del usuario durante un período definido, creando una experiencia más fluida sin avisos de transacción o permitiendo automatizaciones. + + Ver: [Análisis profundo de permisos](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) y [Directorio de tokens](/sdk/web/wallet-sdk/ecosystem/token-directory). + + ### Comportamiento de las opciones de comisión (importante) + + Cuando su aplicación envía transacciones mediante el relayer de Sequence, este necesita determinar **cómo se pagan las comisiones**. + + - Si desea que el SDK solicite automáticamente los permisos necesarios relacionados con comisiones al crear una sesión explícita, active `includeFeeOptionPermissions`. + - Si lo desactiva, usted es responsable de incluir los permisos relacionados con comisiones que requiera la opción de comisión que espera usar. + + Si no se puede cubrir el pago de la comisión, las transacciones pueden fallar al momento de enviarse, incluso si el permiso principal de llamada al contrato parece correcto. - `nativeTokenSpending` es opcional. Si se omite, la sesión tendrá por defecto un `valueLimit` de token nativo de `0`. + `nativeTokenSpending` es opcional. Si se omite, la sesión no tendrá asignado un límite de gasto de tokens nativos. Por ejemplo, creemos una sesión explícita que permita a su dapp `depositar 100 USDC en el pool de AAVE V3 en Arbitrum, en nombre del usuario durante las próximas 24 horas` @@ -82,7 +93,7 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t export const config: any = createConfig({ projectAccessKey: "AQAAAAAAAABtDHG1It7lxRF_9bbxw4diip8", - walletUrl: 'https://next-acme-wallet.sequence-dev.app', + walletUrl: 'https://acme-wallet.ecosystem-demo.xyz', // Optional dappOrigin: window.location.origin, signIn: { @@ -94,7 +105,7 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t google: true, apple: true, email: true, - explicitSessionParams: { + explicitSession: createExplicitSession({ chainId: 42161, nativeTokenSpending: { valueLimit: parseEther('0.01'), // Allow spending up to 0.01 ETH for gas fees @@ -123,7 +134,7 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t ] }) ] - } + }) }); ``` @@ -213,20 +224,20 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t - `dappOrigin` - `signIn.projectName`, `appName` - `chainIds`, `defaultChainId` - - `explicitSessionParams` (opcional; `nativeTokenSpending` por defecto es `valueLimit: 0`) + - `explicitSession` (opcional; solicita permisos y límites explícitos de sesión) - `includeFeeOptionPermissions`, `enableImplicitSession` - `nodesUrl`, `relayerUrl` - `walletConnect` ```typescript [config.ts] - import { createConfig } from "@0xsequence/connect"; + import { createConfig, createExplicitSession } from "@0xsequence/connect"; export const config: any = createConfig({ projectAccessKey: "AQAAAAAAAABtDHG1It7lxRF_9bbxw4diip8", signIn: { projectName: 'Sequence Web SDK Demo', }, - walletUrl: 'https://next-acme-wallet.sequence-dev.app', + walletUrl: 'https://acme-wallet.ecosystem-demo.xyz', dappOrigin: window.location.origin, appName: 'Sequence Web SDK Demo', chainIds: [42161], @@ -234,18 +245,18 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t google: true, apple: true, email: true, - explicitSessionParams: { ... } + explicitSession: createExplicitSession({ ... }) }); ``` - El `walletUrl` es la URL del Ecosystem Wallet que su dApp usará. Para nuestra demo, estamos usando el [Acme Ecosystem Wallet](https://next-acme-wallet.sequence-dev.app). + El `walletUrl` es la URL del Ecosystem Wallet que su dApp utilizará. Para nuestra demostración, estamos usando el [Acme Ecosystem Wallet](https://acme-wallet.ecosystem-demo.xyz). El `dappOrigin` es el origen de su dapp, usado para verificar de dónde proviene el usuario. - El objeto `explicitSessionParams` permite que su dapp solicite permisos específicos al usuario al conectarse. - Estos permisos pueden autorizar a su dapp a realizar ciertas acciones en nombre del usuario durante un período definido, creando una experiencia más fluida sin solicitudes de transacción. + El objeto `explicitSession` permite que su dapp solicite permisos específicos al usuario al conectarse. + Estos permisos pueden autorizar a su dapp a realizar ciertas acciones en nombre del usuario por un periodo definido, creando una experiencia más fluida sin ventanas emergentes de transacción. - `nativeTokenSpending` es opcional. Si se omite, la sesión tendrá por defecto un `valueLimit` de token nativo de `0`. + `nativeTokenSpending` es opcional. Si se omite, la sesión no tendrá asignado un límite de gasto de tokens nativos. Por ejemplo, creemos una sesión explícita que permita a su dapp `depositar 100 USDC en el pool de AAVE V3 en Arbitrum, en nombre del usuario durante las próximas 24 horas` @@ -261,7 +272,7 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t signIn: { projectName: 'Sequence Web SDK Demo', }, - walletUrl: 'https://next-acme-wallet.sequence-dev.app', + walletUrl: 'https://acme-wallet.ecosystem-demo.xyz', dappOrigin: window.location.origin, appName: 'Sequence Web SDK Demo', chainIds: [42161], @@ -269,7 +280,7 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t google: true, apple: true, email: true, - explicitSessionParams: { + explicitSession: createExplicitSession({ chainId: 42161, nativeTokenSpending: { valueLimit: parseEther('0.01'), // Allow spending up to 0.01 ETH for gas fees @@ -298,7 +309,7 @@ Primero, asegúrese de haber creado una cuenta de Sequence Project. Si aún no t ] }) ] - } + }) }); ``` diff --git a/es/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx b/es/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx new file mode 100644 index 00000000..a429b422 --- /dev/null +++ b/es/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx @@ -0,0 +1,91 @@ +--- +description: Guía práctica para construir permisos de sesión explícitos para Ecosystem Wallet (Web SDK) +sidebarTitle: Análisis profundo de permisos +--- + +Esta página recopila orientación práctica y errores comunes al construir **permisos de sesión explícitos** para Ecosystem Wallet (Web SDK / `@0xsequence/connect`). + +Si aún no ha configurado Connect, comience con [Primeros pasos](/sdk/web/wallet-sdk/ecosystem/getting-started). + +--- + +## Modelo mental +Una sesión explícita es una _concesión de autoridad limitada_: +- **Alcance:** qué llamadas están permitidas (destinos + firmas de función + reglas de parámetros) +- **Presupuesto:** cuánto valor puede moverse (límite de gasto nativo, límites ERC20) +- **Tiempo:** ventana de expiración + +Cuando solicita una sesión explícita, el usuario aprueba ese conjunto de permisos en la interfaz de la wallet. Después de la aprobación, su dApp (o una automatización del lado del servidor, según su arquitectura) puede ejecutar transacciones dentro de esos límites sin solicitar repetidamente la aprobación del usuario. + +--- + +## Patrones para construir permisos + +### 1) Permisos específicos por destino (recomendado cuando sea posible) +Si su caso de uso tiene un contrato de destino conocido (por ejemplo, “depositar en un pool de Aave”, “mintear desde este contrato NFT”), prefiera un permiso restringido con: +- una sola `address` +- una `functionSignature` concreta +- reglas de parámetros + +Este es el método más seguro y fácil de razonar. + +### 2) Transferencias a destinatarios abiertos (requiere una construcción diferente) +Si su experiencia de usuario es “enviar tokens a **cualquier** destinatario” (por ejemplo, una app de wallet), está otorgando una autoridad más amplia. + +**Recomendación:** +- Para **transferencias ERC20** abiertas, el enfoque estándar es permitir el contrato de token `transfer(address to, uint256 value)` con una regla de **límite de valor** (y _sin_ regla `to=EQUAL`). +- Para **envíos de tokens nativos** abiertos, use un patrón de **forwarder**. En configuraciones de wallet Sequence, un enfoque común es otorgar permiso de destino al `ValueForwarder` de la cadena y enviar tokens nativos mediante una llamada forward. + +> Si su dApp no necesita destinatarios abiertos, no los otorgue. + +--- + +## Opciones de comisión y por qué importan (comportamiento de envío) +Al enviar una transacción mediante el relay de Sequence, se selecciona una **opción de comisión** para pagar la ejecución. + +### Comportamientos clave + +- Si su aplicación depende de transacciones relayed, el relayer debe poder determinar _cómo se pagan las comisiones_. +- En la práctica, su aplicación debe hacer una de las siguientes: + - activar la inclusión automática de permisos de comisión (ver `includeFeeOptionPermissions`), o + - incluir explícitamente los permisos necesarios relacionados con comisiones en la sesión. + +### Error común +Los desarrolladores suelen construir un permiso de llamada válido (por ejemplo, ERC20 `transfer`) pero omiten los permisos relacionados con comisiones. La transacción puede fallar al enviarse porque el relayer no puede seleccionar una vía válida de pago de comisión. + +**Recomendación:** para la mayoría de las dApps, active `includeFeeOptionPermissions` a menos que tenga una razón para controlar completamente la forma de los permisos de comisión. + +--- + +## Depuración de bajo nivel con `@0xsequence/dapp-client-cli` +El Web SDK abstrae gran parte de la maquinaria subyacente. Cuando necesite depurar "¿qué está haciendo el relayer?", la CLI puede ser una herramienta útil. + +### Flujos de trabajo útiles + +1. **Inspeccionar opciones de comisión** para un paquete de transacciones: + +```bash +npx @0xsequence/dapp-client-cli fee-options \ + --chain-id \ + --transactions '' +``` + +2. **Enviar una transacción** con una opción de comisión elegida explícitamente: + +```bash +npx @0xsequence/dapp-client-cli send-transaction \ + --chain-id \ + --transactions '' \ + --fee-option '' +``` + +3. **Comparar el conjunto de permisos** que solicitó versus las llamadas que intenta realizar. + +Consejo: comience con un conjunto de permisos específicos por destino y amplíe el alcance según sea necesario. + +--- + +## Lecturas recomendadas + +- [Resolución de direcciones de tokens con el Sequence Token Directory](/sdk/web/wallet-sdk/ecosystem/token-directory) +- [Primeros pasos](/sdk/web/wallet-sdk/ecosystem/getting-started) \ No newline at end of file diff --git a/es/sdk/web/wallet-sdk/ecosystem/token-directory.mdx b/es/sdk/web/wallet-sdk/ecosystem/token-directory.mdx new file mode 100644 index 00000000..e600ae39 --- /dev/null +++ b/es/sdk/web/wallet-sdk/ecosystem/token-directory.mdx @@ -0,0 +1,108 @@ +--- +description: Resuelva direcciones y decimales de tokens por cadena usando el Sequence Token Directory +sidebarTitle: Directorio de Tokens +--- + +Cuando un usuario dice “enviar **USDC en Base**” necesita mapear: +- `(chainId, symbol)` → `tokenAddress` +- `symbol` → `decimals` (para `parseUnits`) + +Sequence mantiene un registro validado y multichain de tokens: **Sequence Token Directory**: +- Repositorio: [https://github.com/0xsequence/token-directory](https://github.com/0xsequence/token-directory) +- Índice: `index/index.json` +- Lista ERC20 por cadena: `index//erc20.json` + +Esta página muestra una implementación mínima y amigable con el caché. + +--- + +## Modelo de datos + +### 1) Cargue el índice maestro +Obtener: +- `https://raw.githubusercontent.com/0xsequence/token-directory/main/index/index.json` + +Este archivo le indica qué carpetas de cadenas existen e incluye hashes de contenido. + +### 2) Elija la carpeta de la cadena y obtenga la lista ERC20 +Obtener: +- `https://raw.githubusercontent.com/0xsequence/token-directory/main/index//erc20.json` + +Esta lista sigue el esquema de listas de tokens de Uniswap (los tokens incluyen `address`, `symbol`, `decimals`, etc.). + +--- + +## Ejemplo en Node.js (con caché) + +```ts +import fs from 'node:fs' +import os from 'node:os' +import path from 'node:path' + +const BASE = 'https://raw.githubusercontent.com/0xsequence/token-directory/main' + +function cacheDir() { + return path.join(os.homedir(), '.cache', 'sequence-token-directory') +} + +async function fetchJson(url: string) { + const res = await fetch(url) + if (!res.ok) throw new Error(`fetch failed: ${res.status} ${url}`) + return res.json() +} + +export async function resolveErc20BySymbol(chainId: number, symbol: string) { + const indexUrl = `${BASE}/index/index.json` + const index = await fetchJson(indexUrl) + + // Find chain folder by chainId + let chainName: string | null = null + let sha256: string | null = null + + for (const [name, meta] of Object.entries(index.index)) { + if (name === '_external') continue + if (String(meta?.chainId) !== String(chainId)) continue + chainName = name + sha256 = meta?.tokenLists?.['erc20.json'] || null + break + } + + if (!chainName || !sha256) throw new Error(`No ERC20 list for chainId=${chainId}`) + + // Cache per-chain list by hash + const fp = path.join(cacheDir(), `${chainId}.erc20.${String(sha256).slice(0, 12)}.json`) + if (fs.existsSync(fp)) { + const cached = JSON.parse(fs.readFileSync(fp, 'utf8')) + return cached.tokens.find((t: any) => String(t.symbol).toUpperCase() === symbol.toUpperCase()) || null + } + + const listUrl = `${BASE}/index/${chainName}/erc20.json` + const list = await fetchJson(listUrl) + + fs.mkdirSync(path.dirname(fp), { recursive: true }) + fs.writeFileSync(fp, JSON.stringify(list), 'utf8') + + return list.tokens.find((t: any) => String(t.symbol).toUpperCase() === symbol.toUpperCase()) || null +} +``` + +--- + +## Cómo usarlo en permisos +Una vez que resuelva: +- `token.address` +- `token.decimals` + +Puede: +- construir un permiso para `transfer(address to, uint256 value)` +- construir una interfaz que acepte símbolos en lugar de direcciones + +Ejemplo de regla de permiso (ERC20): +- permitir `transfer(to=ANY, value<=limit)` usando una regla de límite de valor + +--- + +## Dónde se referencia esto + +- [Análisis profundo de permisos](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) +- [Primeros pasos](/sdk/web/wallet-sdk/ecosystem/getting-started) \ No newline at end of file diff --git a/es/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx b/es/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx index 5b9ee4df..1acab321 100644 --- a/es/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx +++ b/es/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx @@ -27,7 +27,9 @@ El Sequence SDK ahora es una dependencia en su proyecto, listo para usarse. ## 🔗 Paso 3: Integre con su app React Finalmente, envuelva su aplicación con nuestro proveedor de wallet. Esto hace que todas las funciones de conexión estén disponibles para cualquier componente dentro de su dApp. -También estamos creando una sesión que solicita permiso para gastar hasta 100 tokens en nombre del usuario, lo que abre la puerta a automatizaciones y mejoras en la experiencia de usuario. +También estamos creando una sesión explícita que solicita permiso para gastar hasta 100 tokens en nombre del usuario, abriendo la puerta a automatizaciones y mejoras de experiencia de usuario. + +Ver: [Análisis profundo de permisos](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) y [Directorio de tokens](/sdk/web/wallet-sdk/ecosystem/token-directory). ```tsx import { SequenceConnect, createConfig, createContractPermission, createExplicitSession, useOpenConnectModal, type SequenceConnectConfig } from "@0xsequence/connect"; diff --git a/ja/sdk/web/wallet-sdk/ecosystem/getting-started.mdx b/ja/sdk/web/wallet-sdk/ecosystem/getting-started.mdx index a7946e05..e55c063a 100644 --- a/ja/sdk/web/wallet-sdk/ecosystem/getting-started.mdx +++ b/ja/sdk/web/wallet-sdk/ecosystem/getting-started.mdx @@ -14,11 +14,11 @@ sidebarTitle: はじめに ```bash - npm install @0xsequence/connect@v6-beta wagmi viem + npm install @0xsequence/connect@v6-beta wagmi viem # or - pnpm install @0xsequence/connect@v6-beta wagmi viem + pnpm install @0xsequence/connect@v6-beta wagmi viem # or - yarn add @0xsequence/connect@v6-beta wagmi viem + yarn add @0xsequence/connect@v6-beta wagmi viem ``` @@ -35,17 +35,17 @@ sidebarTitle: はじめに - `dappOrigin` - `signIn.projectName`, `appName` - `chainIds`, `defaultChainId` - - `explicitSessionParams`(オプション;`nativeTokenSpending`はデフォルトで`valueLimit: 0`) + - `explicitSession`(オプション;明示的なセッション権限と制限をリクエスト) - `includeFeeOptionPermissions`, `enableImplicitSession` - `nodesUrl`, `relayerUrl` - `walletConnect` ```typescript [config.ts] - import { createConfig } from "@0xsequence/connect"; + import { createConfig, createExplicitSession } from "@0xsequence/connect"; export const config: any = createConfig({ projectAccessKey: "AQAAAAAAAABtDHG1It7lxRF_9bbxw4diip8", - walletUrl: 'https://next-acme-wallet.sequence-dev.app', + walletUrl: 'https://acme-wallet.ecosystem-demo.xyz', // Optional dappOrigin: window.location.origin, signIn: { @@ -57,18 +57,29 @@ sidebarTitle: はじめに google: true, apple: true, email: true, - explicitSessionParams: { ... } + explicitSession: createExplicitSession({ ... }) }); ``` - `walletUrl`は、dAppが利用するEcosystem WalletのURLです。デモでは[Acme Ecosystem Wallet](https://next-acme-wallet.sequence-dev.app)を使用しています。 + `walletUrl` は、dApp が利用するエコシステムウォレットのURLです。デモでは、[Acme エコシステムウォレット](https://acme-wallet.ecosystem-demo.xyz) を使用しています。 `dappOrigin`はdappのオリジンで、ユーザーのアクセス元を確認するために使われます。 - `explicitSessionParams` オブジェクトを使うことで、dapp は接続時にユーザーから特定の権限をリクエストできます。 - これらの権限により、dapp は一定期間ユーザーに代わって特定の操作を実行できるようになり、トランザクションの確認画面なしで自動処理やシームレスな体験を実現します。 + `explicitSession`オブジェクトを使うことで、dAppが接続時にユーザーから特定の権限をリクエストできます。 + これらの権限により、ユーザーに取引確認を求めずに一定期間dAppが特定の操作を代行でき、よりシームレスな体験や自動化が可能になります。 + + 参照:[権限の詳細解説](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) および [トークンディレクトリ](/sdk/web/wallet-sdk/ecosystem/token-directory)。 + + ### 手数料オプションの挙動(重要) + + アプリがSequenceリレーを通じてトランザクションを送信する際、リレーラーは**手数料の支払い方法**を判断する必要があります。 + + - 明示的なセッション作成時にSDKが自動で必要な手数料関連の権限をリクエストするようにしたい場合は、`includeFeeOptionPermissions`を有効にしてください。 + - これを無効にした場合、利用する手数料オプションに必要な手数料関連の権限を自分で含める必要があります。 + + 手数料の支払いが満たされない場合、コアのコントラクトコール権限が正しくても、トランザクションは送信時に失敗することがあります。 - `nativeTokenSpending`はオプションです。省略した場合、セッションはネイティブトークンの`valueLimit`が`0`に設定されます。 + `nativeTokenSpending`はオプションです。省略した場合、セッションはネイティブトークンの支出許可なしがデフォルトとなります。 例として、「次の24時間、ユーザーの代理でArbitrum上のAAVE V3プールに100 USDCを入金する」ための明示的セッションを作成してみましょう。 @@ -81,7 +92,7 @@ sidebarTitle: はじめに export const config: any = createConfig({ projectAccessKey: "AQAAAAAAAABtDHG1It7lxRF_9bbxw4diip8", - walletUrl: 'https://next-acme-wallet.sequence-dev.app', + walletUrl: 'https://acme-wallet.ecosystem-demo.xyz', // Optional dappOrigin: window.location.origin, signIn: { @@ -93,7 +104,7 @@ sidebarTitle: はじめに google: true, apple: true, email: true, - explicitSessionParams: { + explicitSession: createExplicitSession({ chainId: 42161, nativeTokenSpending: { valueLimit: parseEther('0.01'), // Allow spending up to 0.01 ETH for gas fees @@ -122,7 +133,7 @@ sidebarTitle: はじめに ] }) ] - } + }) }); ``` @@ -211,20 +222,20 @@ sidebarTitle: はじめに - `dappOrigin` - `signIn.projectName`, `appName` - `chainIds`, `defaultChainId` - - `explicitSessionParams`(オプション;`nativeTokenSpending`はデフォルトで`valueLimit: 0`) + - `explicitSession`(オプション;明示的なセッション権限と制限をリクエスト) - `includeFeeOptionPermissions`, `enableImplicitSession` - `nodesUrl`, `relayerUrl` - `walletConnect` ```typescript [config.ts] - import { createConfig } from "@0xsequence/connect"; + import { createConfig, createExplicitSession } from "@0xsequence/connect"; export const config: any = createConfig({ projectAccessKey: "AQAAAAAAAABtDHG1It7lxRF_9bbxw4diip8", signIn: { projectName: 'Sequence Web SDK Demo', }, - walletUrl: 'https://next-acme-wallet.sequence-dev.app', + walletUrl: 'https://acme-wallet.ecosystem-demo.xyz', dappOrigin: window.location.origin, appName: 'Sequence Web SDK Demo', chainIds: [42161], @@ -232,18 +243,18 @@ sidebarTitle: はじめに google: true, apple: true, email: true, - explicitSessionParams: { ... } + explicitSession: createExplicitSession({ ... }) }); ``` - `walletUrl`は、dAppが利用するEcosystem WalletのURLです。デモでは[Acme Ecosystem Wallet](https://next-acme-wallet.sequence-dev.app)を使用しています。 + `walletUrl` は、dApp が利用するエコシステムウォレットのURLです。デモでは、[Acme エコシステムウォレット](https://acme-wallet.ecosystem-demo.xyz) を使用しています。 `dappOrigin`はdappのオリジンで、ユーザーのアクセス元を確認するために使われます。 - `explicitSessionParams` オブジェクトを使うことで、dapp は接続時にユーザーから特定の権限をリクエストできます。 - これらの権限により、dapp は一定期間ユーザーに代わって特定の操作を実行できるようになり、トランザクションの確認画面なしでよりスムーズなユーザー体験を提供できます。 + `explicitSession`オブジェクトを使うと、接続時にユーザーから特定の権限をリクエストできます。 + これにより、一定期間ユーザーの代理で特定の操作を実行でき、取引プロンプトなしでシームレスな体験を提供します。 - `nativeTokenSpending`はオプションです。省略した場合、セッションはネイティブトークンの`valueLimit`が`0`に設定されます。 + `nativeTokenSpending`はオプションです。省略した場合、セッションはネイティブトークンの支出許可なしがデフォルトとなります。 例として、「次の24時間、ユーザーの代理でArbitrum上のAAVE V3プールに100 USDCを入金する」ための明示的セッションを作成してみましょう。 @@ -259,7 +270,7 @@ sidebarTitle: はじめに signIn: { projectName: 'Sequence Web SDK Demo', }, - walletUrl: 'https://next-acme-wallet.sequence-dev.app', + walletUrl: 'https://acme-wallet.ecosystem-demo.xyz', dappOrigin: window.location.origin, appName: 'Sequence Web SDK Demo', chainIds: [42161], @@ -267,7 +278,7 @@ sidebarTitle: はじめに google: true, apple: true, email: true, - explicitSessionParams: { + explicitSession: createExplicitSession({ chainId: 42161, nativeTokenSpending: { valueLimit: parseEther('0.01'), // Allow spending up to 0.01 ETH for gas fees @@ -296,7 +307,7 @@ sidebarTitle: はじめに ] }) ] - } + }) }); ``` diff --git a/ja/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx b/ja/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx new file mode 100644 index 00000000..1ae9344a --- /dev/null +++ b/ja/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx @@ -0,0 +1,91 @@ +--- +description: Ecosystemウォレット(Web SDK)向け明示的セッション権限の構築に関する実践的ガイド +sidebarTitle: 権限の詳細解説 +--- + +このページでは、Ecosystemウォレット(Web SDK / `@0xsequence/connect`)向け**明示的セッション権限**の構築時に役立つ実践的なガイドやよくある注意点をまとめています。 + +まだConnectのセットアップが済んでいない場合は、[はじめに](/sdk/web/wallet-sdk/ecosystem/getting-started)から始めてください。 + +--- + +## 考え方のモデル +明示的なセッションは、\_範囲が限定された権限付与\_です: +- **範囲:** 許可される呼び出し(ターゲット+関数シグネチャ+パラメータルール) +- **予算:** 移動できる価値の上限(ネイティブ支出制限、ERC20制限) +- **期間:** 有効期限ウィンドウ + +明示的なセッションをリクエストすると、ユーザーはウォレットUIでその権限セットを承認します。承認後、dApp(またはアーキテクチャによってはサーバー側の自動化)が、その範囲内でユーザーへの再承認なしにトランザクションを実行できます。 + +--- + +## 権限構築パターン + +### 1)ターゲット特定型の権限(可能な場合は推奨) +利用ケースで既知のコントラクトターゲットがある場合(例:「Aaveプールへの入金」「このNFTコントラクトからのミント」)、以下のような厳格な権限を推奨します: +- 単一の`address` +- 具体的な`functionSignature` +- パラメータルール + +これが最も安全で、理解しやすい方法です。 + +### 2)送信先が自由なトークン送信(異なる構築が必要) +UXが「**任意の**受取人にトークンを送る」(例:ウォレットアプリ体験)の場合、より広い権限を付与することになります。 + +**ガイダンス:** +- 送信先が自由な**ERC20送信**の場合、標準的な方法はトークンコントラクトの`transfer(address to, uint256 value)`を**金額制限**ルール付きで許可することです(`to=EQUAL`ルールは付けません)。 +- 送信先が自由な**ネイティブトークン送信**の場合は、**フォワーダー**パターンを使います。Sequenceウォレット構成では、チェーンの`ValueForwarder`にターゲット権限を与え、フォワードコールでネイティブ送信するのが一般的です。 + +> dAppで送信先が自由である必要がない場合は、その権限を与えないでください。 + +--- + +## 手数料オプションとその重要性(送信時の挙動) +Sequenceリレーを通じてトランザクションを送信する際、**手数料オプション**が選択され、実行のための手数料が支払われます。 + +### 主な挙動 + +- アプリがリレートランザクションに依存する場合、リレーラーは\_手数料の支払い方法\_を判断できなければなりません。 +- 実際には、アプリは次のいずれかを行うべきです: + - 自動手数料権限の付与を有効にする(`includeFeeOptionPermissions`を参照)、または + - 必要な手数料関連の権限をセッションに明示的に含める。 + +### よくある注意点 +開発者はしばしば有効なコール権限(例:ERC20の`transfer`)を構築しますが、手数料関連の権限を省略してしまいます。その場合、リレーラーが有効な手数料支払い経路を選択できず、送信時にトランザクションが失敗することがあります。 + +**推奨:** ほとんどのdAppでは、特別な理由がない限り`includeFeeOptionPermissions`を有効にしてください。 + +--- + +## `@0xsequence/dapp-client-cli`による低レベルデバッグ +Web SDKは多くの内部処理を抽象化しています。「リレーラーが何をしているのか?」をデバッグしたい場合、CLIが役立ちます。 + +### 便利なワークフロー + +1. **トランザクションバンドルの手数料オプションを確認**: + +```bash +npx @0xsequence/dapp-client-cli fee-options \ + --chain-id \ + --transactions '' +``` + +2. **明示的に選択した手数料オプションでトランザクションを送信**: + +```bash +npx @0xsequence/dapp-client-cli send-transaction \ + --chain-id \ + --transactions '' \ + --fee-option '' +``` + +3. **リクエストした権限セットと実際に行おうとしている呼び出しを比較**。 + +ヒント:まずターゲット特定型の権限セットから始め、必要に応じて範囲を広げていきましょう。 + +--- + +## 次に読むのにおすすめ + +- [Sequenceトークンディレクトリによるトークンアドレス解決](/sdk/web/wallet-sdk/ecosystem/token-directory) +- [はじめに](/sdk/web/wallet-sdk/ecosystem/getting-started) \ No newline at end of file diff --git a/ja/sdk/web/wallet-sdk/ecosystem/token-directory.mdx b/ja/sdk/web/wallet-sdk/ecosystem/token-directory.mdx new file mode 100644 index 00000000..70d906f0 --- /dev/null +++ b/ja/sdk/web/wallet-sdk/ecosystem/token-directory.mdx @@ -0,0 +1,108 @@ +--- +description: Sequenceトークンディレクトリを使って、チェーンごとにトークンアドレスと小数点を解決できます +sidebarTitle: トークンディレクトリ +--- + +ユーザーが「**Base上のUSDCを送る**」と言った場合、次のようにマッピングする必要があります: +- `(chainId, symbol)` → `tokenAddress` +- `symbol` → `decimals`(`parseUnits`用) + +Sequenceは検証済みのマルチチェーントークンレジストリ:**Sequenceトークンディレクトリ**を管理しています: +- リポジトリ:[https://github.com/0xsequence/token-directory](https://github.com/0xsequence/token-directory) +- インデックス:`index/index.json` +- チェーンごとのERC20リスト:`index//erc20.json` + +このページでは、最小限かつキャッシュに優しい実装例を紹介します。 + +--- + +## データモデル + +### 1)マスターインデックスを読み込む +取得: +- `https://raw.githubusercontent.com/0xsequence/token-directory/main/index/index.json` + +このファイルには、どのチェーンフォルダが存在するかや、コンテンツハッシュが含まれています。 + +### 2)チェーンフォルダを選び、ERC20リストを取得 +取得: +- `https://raw.githubusercontent.com/0xsequence/token-directory/main/index//erc20.json` + +このリストはUniswapトークンリストスキーマに従っています(トークンには`address`、`symbol`、`decimals`などが含まれます)。 + +--- + +## Node.jsの例(キャッシュ対応) + +```ts +import fs from 'node:fs' +import os from 'node:os' +import path from 'node:path' + +const BASE = 'https://raw.githubusercontent.com/0xsequence/token-directory/main' + +function cacheDir() { + return path.join(os.homedir(), '.cache', 'sequence-token-directory') +} + +async function fetchJson(url: string) { + const res = await fetch(url) + if (!res.ok) throw new Error(`fetch failed: ${res.status} ${url}`) + return res.json() +} + +export async function resolveErc20BySymbol(chainId: number, symbol: string) { + const indexUrl = `${BASE}/index/index.json` + const index = await fetchJson(indexUrl) + + // Find chain folder by chainId + let chainName: string | null = null + let sha256: string | null = null + + for (const [name, meta] of Object.entries(index.index)) { + if (name === '_external') continue + if (String(meta?.chainId) !== String(chainId)) continue + chainName = name + sha256 = meta?.tokenLists?.['erc20.json'] || null + break + } + + if (!chainName || !sha256) throw new Error(`No ERC20 list for chainId=${chainId}`) + + // Cache per-chain list by hash + const fp = path.join(cacheDir(), `${chainId}.erc20.${String(sha256).slice(0, 12)}.json`) + if (fs.existsSync(fp)) { + const cached = JSON.parse(fs.readFileSync(fp, 'utf8')) + return cached.tokens.find((t: any) => String(t.symbol).toUpperCase() === symbol.toUpperCase()) || null + } + + const listUrl = `${BASE}/index/${chainName}/erc20.json` + const list = await fetchJson(listUrl) + + fs.mkdirSync(path.dirname(fp), { recursive: true }) + fs.writeFileSync(fp, JSON.stringify(list), 'utf8') + + return list.tokens.find((t: any) => String(t.symbol).toUpperCase() === symbol.toUpperCase()) || null +} +``` + +--- + +## 権限での使い方 +次の情報が解決できたら: +- `token.address` +- `token.decimals` + +以下が可能です: +- `transfer(address to, uint256 value)`用の権限を構築 +- アドレスの代わりにシンボルを受け付けるUIを作成 + +権限ルール例(ERC20): +- 金額制限ルールを使い、`transfer(to=ANY, value<=limit)`を許可 + +--- + +## この内容が参照されている場所 + +- [権限の詳細解説](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) +- [はじめに](/sdk/web/wallet-sdk/ecosystem/getting-started) \ No newline at end of file diff --git a/ja/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx b/ja/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx index 3b78f8d6..ff310ae4 100644 --- a/ja/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx +++ b/ja/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx @@ -27,7 +27,9 @@ pnpm install @0xsequence/connect@v6-beta ## 🔗 ステップ3:Reactアプリに統合 最後に、アプリケーション全体をウォレットプロバイダーでラップします。これにより、dApp内のどのコンポーネントからも接続機能が利用できるようになります。 -また、ユーザーに代わって最大100トークンまで使用できる権限をリクエストするセッションも作成しています。これにより自動化やUXの向上が可能になります。 +また、ユーザーの代わりに最大100トークンまで利用できる権限をリクエストする明示的なセッションも作成しており、自動化やUX向上の可能性が広がります。 + +参照:[権限の詳細解説](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) および [トークンディレクトリ](/sdk/web/wallet-sdk/ecosystem/token-directory)。 ```tsx import { SequenceConnect, createConfig, createContractPermission, createExplicitSession, useOpenConnectModal, type SequenceConnectConfig } from "@0xsequence/connect"; diff --git a/sdk/web/wallet-sdk/ecosystem/getting-started.mdx b/sdk/web/wallet-sdk/ecosystem/getting-started.mdx index 87681506..d3dd23a1 100644 --- a/sdk/web/wallet-sdk/ecosystem/getting-started.mdx +++ b/sdk/web/wallet-sdk/ecosystem/getting-started.mdx @@ -38,13 +38,13 @@ Next, create the Ecosystem Wallet configuration. - `dappOrigin` - `signIn.projectName`, `appName` - `chainIds`, `defaultChainId` -- `explicitSessionParams` (optional; `nativeTokenSpending` defaults to `valueLimit: 0`) +- `explicitSession` (optional; request explicit session permissions + limits) - `includeFeeOptionPermissions`, `enableImplicitSession` - `nodesUrl`, `relayerUrl` - `walletConnect` ```typescript [config.ts] -import { createConfig } from "@0xsequence/connect"; +import { createConfig, createExplicitSession } from "@0xsequence/connect"; export const config: any = createConfig({ projectAccessKey: "AQAAAAAAAABtDHG1It7lxRF_9bbxw4diip8", @@ -60,7 +60,7 @@ export const config: any = createConfig({ google: true, apple: true, email: true, - explicitSessionParams: { ... } + explicitSession: createExplicitSession({ ... }) }); ``` @@ -68,10 +68,21 @@ The `walletUrl` is the URL of the Ecosystem Wallet your dApp will use, for our d The `dappOrigin` is the origin of your dapp, used to verify where the user is coming from. -The `explicitSessionParams` object allows your dapp to request specific permissions from the user upon connection. +The `explicitSession` object allows your dapp to request specific permissions from the user upon connection. These permissions can authorize your dapp to perform certain actions on the user's behalf for a defined period, creating a more seamless user experience with no transaction prompts or allowing automations. -`nativeTokenSpending` is optional. If omitted, the session will default to a native token `valueLimit` of `0`. +See: [Permissions Deep Dive](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) and [Token Directory](/sdk/web/wallet-sdk/ecosystem/token-directory). + +### Fee options behavior (important) + +When your app sends transactions via Sequence relaying, the relayer needs to determine **how fees are paid**. + +- If you want the SDK to automatically request the necessary fee-related permissions when creating an explicit session, enable `includeFeeOptionPermissions`. +- If you disable it, you are responsible for including whatever fee-related permissions are required for the fee option you expect to use. + +If fee payment cannot be satisfied, transactions may fail at dispatch time even if the core contract-call permission looks correct. + +`nativeTokenSpending` is optional. If omitted, the session will default to no native-token spending allowance. For example, let's create an explicit session that allows your dapp to `deposit 100 USDC into the AAVE V3 pool on Arbitrum, on behalf of the user for the next 24 hours` @@ -96,7 +107,7 @@ export const config: any = createConfig({ google: true, apple: true, email: true, - explicitSessionParams: { + explicitSession: createExplicitSession({ chainId: 42161, nativeTokenSpending: { valueLimit: parseEther('0.01'), // Allow spending up to 0.01 ETH for gas fees @@ -125,7 +136,7 @@ export const config: any = createConfig({ ] }) ] - } + }) }); ``` @@ -229,13 +240,13 @@ Next, create the Ecosystem Wallet configuration. - `dappOrigin` - `signIn.projectName`, `appName` - `chainIds`, `defaultChainId` -- `explicitSessionParams` (optional; `nativeTokenSpending` defaults to `valueLimit: 0`) +- `explicitSession` (optional; request explicit session permissions + limits) - `includeFeeOptionPermissions`, `enableImplicitSession` - `nodesUrl`, `relayerUrl` - `walletConnect` ```typescript [config.ts] -import { createConfig } from "@0xsequence/connect"; +import { createConfig, createExplicitSession } from "@0xsequence/connect"; export const config: any = createConfig({ projectAccessKey: "AQAAAAAAAABtDHG1It7lxRF_9bbxw4diip8", @@ -250,7 +261,7 @@ export const config: any = createConfig({ google: true, apple: true, email: true, - explicitSessionParams: { ... } + explicitSession: createExplicitSession({ ... }) }); ``` @@ -258,10 +269,10 @@ The `walletUrl` is the URL of the Ecosystem Wallet you dApp will use, for our de The `dappOrigin` is the origin of your dapp, used to verify where the user is coming from. -The `explicitSessionParams` object allows your dapp to request specific permissions from the user upon connection. +The `explicitSession` object allows your dapp to request specific permissions from the user upon connection. These permissions can authorize your dapp to perform certain actions on the user's behalf for a defined period, creating a more seamless user experience with no transaction prompts. -`nativeTokenSpending` is optional. If omitted, the session will default to a native token `valueLimit` of `0`. +`nativeTokenSpending` is optional. If omitted, the session will default to no native-token spending allowance. For example, let's create an explicit session that allows your dapp to `deposit 100 USDC into the AAVE V3 pool on Arbitrum, on behalf of the user for the next 24 hours` @@ -285,7 +296,7 @@ export const config: any = createConfig({ google: true, apple: true, email: true, - explicitSessionParams: { + explicitSession: createExplicitSession({ chainId: 42161, nativeTokenSpending: { valueLimit: parseEther('0.01'), // Allow spending up to 0.01 ETH for gas fees @@ -314,7 +325,7 @@ export const config: any = createConfig({ ] }) ] - } + }) }); ``` diff --git a/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx b/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx new file mode 100644 index 00000000..338ca949 --- /dev/null +++ b/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive.mdx @@ -0,0 +1,100 @@ +--- +description: Practical guidance for constructing explicit session permissions for Ecosystem Wallet (Web SDK) +sidebarTitle: Permissions Deep Dive +--- + +This page collects practical guidance and common gotchas when constructing **explicit session permissions** for the Ecosystem Wallet (Web SDK / `@0xsequence/connect`). + +If you haven’t set up Connect yet, start with [Getting Started](/sdk/web/wallet-sdk/ecosystem/getting-started). + +--- + +## Mental model + +An explicit session is a *bounded authority grant*: + +- **Scope:** what calls are allowed (targets + function signatures + parameter rules) +- **Budget:** how much value can move (native spend limit, ERC20 limits) +- **Time:** expiration window + +When you request an explicit session, the user approves that permission set in the wallet UI. After approval, your dApp (or server-side automation, depending on your architecture) can execute transactions within those boundaries without repeatedly prompting the user. + +--- + +## Permission construction patterns + +### 1) Target-specific permissions (recommended when possible) + +If your use case has a known contract target (e.g. “deposit into Aave pool”, “mint from this NFT contract”), prefer a tight permission with: + +- a single `address` +- a concrete `functionSignature` +- parameter rules + +This is the most secure and easiest to reason about. + +### 2) Open-ended recipient transfers (requires different construction) + +If your UX is “send tokens to **any** recipient” (e.g. a wallet app experience), you are granting broader authority. + +**Guidance:** + +- For open-ended **ERC20 transfers**, the canonical approach is allowing the token contract `transfer(address to, uint256 value)` with a **value limit** rule (and *no* `to=EQUAL` rule). +- For open-ended **native token sends**, use a **forwarder** pattern. In Sequence wallet configurations, a common approach is granting a target permission for the chain’s `ValueForwarder` and sending native via a forward call. + +> If your dApp does not need open-ended recipients, don’t grant them. + +--- + +## Fee options & why they matter (dispatch behavior) + +When sending a transaction via Sequence relaying, a **fee option** is selected to pay for execution. + +### Key behaviors + +- If your app relies on relayed transactions, the relayer must be able to determine *how fees are paid*. +- In practice, your app should either: + - enable automatic fee permission inclusion (see `includeFeeOptionPermissions`), or + - explicitly include the required fee-related permissions in the session. + +### Common gotcha + +Developers often construct a perfectly valid call permission (e.g. ERC20 `transfer`) but omit fee-related permissions. The transaction may then fail at dispatch time because the relayer cannot select a valid fee payment path. + +**Recommendation:** for most dApps, enable `includeFeeOptionPermissions` unless you have a reason to fully control the fee-permission shape. + +--- + +## Lower-level debugging with `@0xsequence/dapp-client-cli` + +The Web SDK abstracts much of the underlying machinery. When you need to debug "what is the relayer doing?", the CLI can be a useful lens. + +### Helpful workflows + +1) **Inspect fee options** for a transaction bundle: + +```bash +npx @0xsequence/dapp-client-cli fee-options \ + --chain-id \ + --transactions '' +``` + +2) **Send a transaction** with an explicitly chosen fee option: + +```bash +npx @0xsequence/dapp-client-cli send-transaction \ + --chain-id \ + --transactions '' \ + --fee-option '' +``` + +3) **Compare the permission set** you requested vs the calls you are attempting to make. + +Tip: start from a target-specific permission set, then progressively widen scope as needed. + +--- + +## Recommended next reading + +- [Token address resolution with the Sequence Token Directory](/sdk/web/wallet-sdk/ecosystem/token-directory) +- [Getting Started](/sdk/web/wallet-sdk/ecosystem/getting-started) diff --git a/sdk/web/wallet-sdk/ecosystem/token-directory.mdx b/sdk/web/wallet-sdk/ecosystem/token-directory.mdx new file mode 100644 index 00000000..dc48b2e6 --- /dev/null +++ b/sdk/web/wallet-sdk/ecosystem/token-directory.mdx @@ -0,0 +1,118 @@ +--- +description: Resolve token addresses and decimals per chain using the Sequence Token Directory +sidebarTitle: Token Directory +--- + +When a user says “send **USDC on Base**” you need to map: + +- `(chainId, symbol)` → `tokenAddress` +- `symbol` → `decimals` (for `parseUnits`) + +Sequence maintains a validated, multi-chain token registry: **Sequence Token Directory**: + +- Repo: https://github.com/0xsequence/token-directory +- Index: `index/index.json` +- Per-chain ERC20 list: `index//erc20.json` + +This page shows a minimal, cache-friendly implementation. + +--- + +## Data model + +### 1) Load the master index + +Fetch: + +- `https://raw.githubusercontent.com/0xsequence/token-directory/main/index/index.json` + +This file tells you which chain folders exist and includes content hashes. + +### 2) Pick the chain folder and fetch the ERC20 list + +Fetch: + +- `https://raw.githubusercontent.com/0xsequence/token-directory/main/index//erc20.json` + +This list follows the Uniswap token list schema (tokens include `address`, `symbol`, `decimals`, etc.). + +--- + +## Node.js example (with caching) + +```ts +import fs from 'node:fs' +import os from 'node:os' +import path from 'node:path' + +const BASE = 'https://raw.githubusercontent.com/0xsequence/token-directory/main' + +function cacheDir() { + return path.join(os.homedir(), '.cache', 'sequence-token-directory') +} + +async function fetchJson(url: string) { + const res = await fetch(url) + if (!res.ok) throw new Error(`fetch failed: ${res.status} ${url}`) + return res.json() +} + +export async function resolveErc20BySymbol(chainId: number, symbol: string) { + const indexUrl = `${BASE}/index/index.json` + const index = await fetchJson(indexUrl) + + // Find chain folder by chainId + let chainName: string | null = null + let sha256: string | null = null + + for (const [name, meta] of Object.entries(index.index)) { + if (name === '_external') continue + if (String(meta?.chainId) !== String(chainId)) continue + chainName = name + sha256 = meta?.tokenLists?.['erc20.json'] || null + break + } + + if (!chainName || !sha256) throw new Error(`No ERC20 list for chainId=${chainId}`) + + // Cache per-chain list by hash + const fp = path.join(cacheDir(), `${chainId}.erc20.${String(sha256).slice(0, 12)}.json`) + if (fs.existsSync(fp)) { + const cached = JSON.parse(fs.readFileSync(fp, 'utf8')) + return cached.tokens.find((t: any) => String(t.symbol).toUpperCase() === symbol.toUpperCase()) || null + } + + const listUrl = `${BASE}/index/${chainName}/erc20.json` + const list = await fetchJson(listUrl) + + fs.mkdirSync(path.dirname(fp), { recursive: true }) + fs.writeFileSync(fp, JSON.stringify(list), 'utf8') + + return list.tokens.find((t: any) => String(t.symbol).toUpperCase() === symbol.toUpperCase()) || null +} +``` + +--- + +## How to use it in permissions + +Once you resolve: + +- `token.address` +- `token.decimals` + +You can: + +- build a permission for `transfer(address to, uint256 value)` +- build a UI that accepts symbols instead of addresses + +Example permission rule (ERC20): + +- allow `transfer(to=ANY, value<=limit)` using a value limit rule + +--- + +## Where this is referenced + +- [Permissions Deep Dive](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) +- [Getting Started](/sdk/web/wallet-sdk/ecosystem/getting-started) diff --git a/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx b/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx index 7b327022..b94506e1 100644 --- a/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx +++ b/solutions/wallets/developers/ecosystem-wallet/react_quickstart.mdx @@ -30,7 +30,9 @@ The Sequence SDK is now a dependency in your project, ready to be used. Finally, wrap your application with our wallet provider. This makes all connect features available to any component within your dApp. -We are also creating a session that requests a permission to spend up to 100 tokens on behalf of the user, opening the door automations and UX improvements. +We are also creating an explicit session that requests a permission to spend up to 100 tokens on behalf of the user, opening the door to automations and UX improvements. + +See: [Permissions Deep Dive](/sdk/web/wallet-sdk/ecosystem/permissions-deep-dive) and [Token Directory](/sdk/web/wallet-sdk/ecosystem/token-directory). ```tsx import { SequenceConnect, createConfig, createContractPermission, createExplicitSession, useOpenConnectModal, type SequenceConnectConfig } from "@0xsequence/connect";