L'expérience web3 ultime : déverrouillez vos portefeuilles et signez vos transactions en un clin d'œil, avec des passkeys récupérables.
Organigram Passkey Wallet est un portefeuille Ethereum léger fondé sur les passkeys WebAuthn. Il offre aux utilisateurs l'expérience quotidienne qu'ils attendent des applications modernes sans mot de passe, tout en préservant la propriété essentielle du web3 : posséder pleinement et en toute sécurité une adresse Ethereum standard.
Pas de déploiement fastidieux de smart account. Pas de création de compte réseau par réseau. Pas de service de garde des clés. Pas d'enfermement dans un protocole. Simplement un EOA standard, chiffré côté client, déverrouillé par des passkeys renouvelables et exposé via Wagmi et RainbowKit.
pnpm add @organigram/passkey-wallet
La plupart des parcours d'accueil web3 demandent encore aux utilisateurs de comprendre les extensions de navigateur, les phrases de récupération, les appareils matériels, l'abstraction de compte, le sponsoring du gas, les contrats de récupération, les déploiements propres à chaque réseau, les permissions des signataires... avant même d'avoir utilisé le produit. Organigram Passkey Wallet emprunte un chemin plus simple.
L'utilisateur crée un portefeuille dans le navigateur. Ce portefeuille est un EOA Ethereum ordinaire dérivé d'une phrase de récupération. Cette phrase est chiffrée localement avec une clé dérivée de la sortie PRF d'une passkey WebAuthn, puis stockée uniquement sous forme d'enveloppe de coffre chiffrée. Quand l'utilisateur revient, sa passkey déverrouille le coffre et l'EOA signe messages et transactions comme n'importe quel autre portefeuille.
Le résultat est une expérience de portefeuille qui semble native au web :
Les utilisateurs déverrouillent le portefeuille avec une passkey WebAuthn. Une fois déverrouillé, le portefeuille signe messages, données typées et transactions avec l'EOA sous-jacent.
Le portefeuille expose la même interface que celle que les dapps attendent déjà des portefeuilles injectés, des portefeuilles WalletConnect et des connecteurs RainbowKit. Il prend en charge les demandes de compte, le changement de chaîne, la signature de messages et de données typées, et l'envoi de transactions, comme tout portefeuille standard.
Les utilisateurs peuvent ajouter d'autres passkeys pour la même adresse. Un téléphone de secours, un ordinateur portable, un gestionnaire de mots de passe ou une clé de sécurité peuvent déverrouiller le même coffre chiffré.
L'adresse est un EOA standard : elle existe partout où existent des comptes EVM. Inutile de déployer des contrats de compte sur chaque réseau avant que l'utilisateur puisse commencer.
Les passkeys simplifient l'usage quotidien, tandis que la possibilité d'exporter la phrase de récupération préserve la portabilité et donne aux utilisateurs une issue de secours au cas où toutes leurs passkeys seraient perdues.
L'application exporte un coffre chiffré qui peut être enregistré et restauré depuis n'importe où. Utilisez des serveurs distants, enregistrez-le localement ou dans un gestionnaire de mots de passe sans crainte de divulguer d'informations sensibles.
Ce paquet construit une application prête pour la production, qui sert le portefeuille en local ou sur des domaines personnalisés.
pnpm devpnpm build:artifact
build:artifact compile la bibliothèque TypeScript dans app-dist, et emballe une archive déterministe
artifacts/passkey-wallet-app-v<version>.tar.gz avec un .sha256 de contrôle et un manifeste.
pnpm dev sert le portefeuille à l'adresse https://localhost:3002, derrière un proxy HTTPS placé devant Vite (port 3003). Le premier lancement crée un certificat local avec
mkcert.
Tout autre nom d'hôte peut être passé en argument (pnpm dev my.host.test) : le certificat est alors régénéré pour l'inclure.
Vous n'avez pas à faire confiance aux serveurs de wallet.organigram.ai, ni au code qu'ils servent, pour utiliser vos comptes Organigram. Le profil local-organigram sert votre propre copie du portefeuille, construite à partir de ce code source, sur votre machine :
pnpm dev local-organigram
(ou pnpm passkey-wallet dev local-organigram depuis la racine du dépôt), puis ouvrez https://local.wallet.organigram.ai:3002.
local.wallet.organigram.ai est un sous-domaine de wallet.organigram.ai, donc cette copie déverrouille les mêmes passkeys, et donc les mêmes comptes : le profil fixe le RP ID des passkeys à wallet.organigram.ai. Son stockage navigateur est distinct : restaurez-y donc une fois votre coffre chiffré (voir Coffres récupérables) ; votre passkey le déverrouille ensuite comme d'habitude. Vos clés ne quittent jamais votre navigateur, et la connexion ne dépend plus de la disponibilité ni de l'intégrité de wallet.organigram.ai.
Le nom pointe déjà vers 127.0.0.1 via le DNS public, aucune configuration n'est donc nécessaire. Pour une garantie plus forte, déclarez-le aussi dans votre fichier hosts : sinon, un enregistrement DNS falsifié pourrait le rediriger vers un serveur capable de demander la sortie PRF de vos passkeys (macOS et Linux) :
grep -q 'local.wallet.organigram.ai' /etc/hosts || echo '127.0.0.1 local.wallet.organigram.ai' | sudo tee -a /etc/hosts
Pour l'utiliser depuis n'importe quelle application, activez Paramètres → Votre propre portefeuille sur wallet.organigram.ai. Les requêtes vont alors vers votre copie et, dès qu'elle a répondu, les applications l'ouvrent directement : wallet.organigram.ai n'est plus chargé du tout. Si votre copie cesse de répondre, par exemple parce qu'elle n'est pas lancée, la requête revient vers wallet.organigram.ai au bout de quelques secondes.
Les applications qui utilisent ce paquet acceptent la copie locale du portefeuille officiel sans aucun réglage, sur leurs pages comme sur leurs points d'accès au portefeuille (défi de connexion, sauvegardes de coffres, RPC).
Un portefeuille déployé ailleurs peut offrir la même chose à ses utilisateurs avec sa propre copie locale, servie sous un sous-domaine de son hôte afin qu'elle déverrouille les mêmes passkeys :
localWalletOrigin dans
passkey-wallet.config.json (ou PASSKEY_WALLET_LOCAL_WALLET_ORIGIN au moment du build), par exemple https://local.wallet.example.com:3002;PASSKEY_WALLET_PASSKEY_RP_ID=wallet.example.com pnpm dev local.wallet.example.com;NEXT_PUBLIC_ORGANIGRAM_PASSKEY_WALLET_LOCAL_URL, à côté de
NEXT_PUBLIC_ORGANIGRAM_PASSKEY_WALLET_URL. La valeur est ignorée si ce n'est pas un sous-domaine HTTPS de l'hôte du portefeuille.Chaque build de production de https://wallet.organigram.ai est publié comme release de ce dépôt, avec le SHA-256 de chaque fichier servi. Pour vérifier que le portefeuille en ligne sert l'une de ces releases sans modification, lancez depuis un clone de ce dépôt :
node scripts/verify-runtime-dist.mjs --url https://wallet.organigram.ai
Avec Node.js 24 et pnpm 10.28, reconstruire le commit d'une release reproduit ses fichiers :
pnpm install --frozen-lockfilepnpm run buildnode scripts/verify-runtime-dist.mjs --dist app-dist --manifest <release manifest>
Browser WebAuthn passkey with PRF | v HKDF-derived vault key | v AES-GCM encrypted wallet vault envelope | v Recovery phrase -> EOA -> EIP-1193 providerServer WebAuthn challenges Credential public keys Credential counters Encrypted vault envelopes
En pratique, le déroulement est le suivant :
residentKey: "required",
userVerification: "required", et l'extension prf .Les secrets du portefeuille sont générés et déchiffrés dans le navigateur. Le serveur ne stocke que les éléments de vérification WebAuthn et les enveloppes chiffrées des coffres. Il n'a jamais besoin de la phrase de récupération, de la clé privée ni du coffre déchiffré de l'utilisateur.
Créez et déverrouillez des coffres dans l'interface avec les fonctions du portefeuille :
import { createGeneratedRecoveryPhrase, registerBrowserPasskeyVault, unlockBrowserPasskeyVault} from '@organigram/passkey-wallet/browser-wallet'const registration = await registerBrowserPasskeyVault({ recoveryPhrase: createGeneratedRecoveryPhrase(), name: 'Account 1'})const unlocked = await unlockBrowserPasskeyVault({ records: [registration.record]})const signature = await unlocked.wallet.account.signMessage({ message: 'gm'})
La cérémonie de passkey et le déchiffrement du coffre ont lieu sur l'origine du portefeuille. Les dapps doivent s'intégrer via le connecteur distant.
import { connectorsForWallets } from '@rainbow-me/rainbowkit'import { createConfig, http } from 'wagmi'import { mainnet, sepolia } from 'wagmi/chains'import { createOrganigramRemotePasskeyWallet} from '@organigram/passkey-wallet/remote-rainbowkit'const passkeyWallet = createOrganigramRemotePasskeyWallet({ walletOrigin: 'https://wallet.organigram.ai'})export const wagmiConfig = createConfig({ chains: [mainnet, sepolia], connectors: connectorsForWallets( [ { groupName: 'Recommended', wallets: [() => passkeyWallet] } ], { appName: 'Your App', projectId: 'walletconnect-project-id' } ), transports: { [mainnet.id]: http(), [sepolia.id]: http() }})
Du point de vue de la dapp, il se comporte comme un portefeuille. Un appel à
personal_sign, eth_signTypedData_v4, ou eth_sendTransaction passe par l'origine du portefeuille, où l'utilisateur approuve la requête.
L'application du portefeuille est statique. Un serveur est facultatif et ne doit recevoir que des sauvegardes chiffrées ou des défis de connexion des dapps. Il ne doit ni créer d'identifiants WebAuthn, ni déverrouiller de coffres, ni recevoir de secrets déchiffrés du portefeuille.
Un portefeuille à passkeys ne doit jamais dépendre d'un seul authentificateur.
Organigram Passkey Wallet permet d'ajouter une autre passkey au même portefeuille en rechiffrant le même contenu de coffre pour un nouvel identifiant. L'adresse ne change pas. L'utilisateur garde le même EOA tout en ajoutant une passkey d'ordinateur, de téléphone, de gestionnaire de mots de passe ou une clé de sécurité matérielle.
Le renouvellement suit la même idée à l'inverse : ne retirer les identifiants obsolètes que s'il reste une autre méthode de récupération. Le paquet fournit les briques du portefeuille et des enveloppes ; c'est à votre produit de définir la politique d'expérience utilisateur pour la suppression, la confirmation et le nombre minimal de sauvegardes.
Les passkeys simplifient l'usage quotidien du portefeuille, mais les utilisateurs ont toujours besoin d'une issue de secours.
Organigram Passkey Wallet garde le portefeuille portable en dérivant l'EOA d'une phrase de récupération standard. Si toutes les passkeys sont perdues, l'utilisateur peut récupérer le compte avec cette phrase, ou l'utiliser dans n'importe quel autre portefeuille.
La phrase de récupération doit toujours être exportée avant que l'utilisateur perde toutes ses passkeys. Le paquet fournit une fonction pour exporter la phrase de récupération après une cérémonie WebAuthn réussie, mais ne peut plus le faire une fois tout accès au coffre perdu.
Organigram Passkey Wallet est non custodial par conception.
Le navigateur crée le portefeuille. Le navigateur chiffre le coffre. Le navigateur déchiffre le coffre après une cérémonie WebAuthn réussie. Le serveur stocke les enveloppes chiffrées et vérifie que les réponses WebAuthn sont valides pour le défi, l'origine, le RP ID et la clé publique d'identifiant attendus.
Ce modèle suppose que :
Les passkeys sont créées pour le nom d'hôte exact qui sert le portefeuille (par exemple
wallet.organigram.ai). Toute page servie sous le RP ID des passkeys peut demander la sortie PRF qui déchiffre le coffre : aucune autre application ne doit donc y être hébergée. Les dapps n'ont jamais besoin du RP ID du portefeuille : elles l'atteignent via sa fenêtre popup et postMessage.
Un portefeuille servi depuis un sous-domaine peut réutiliser les passkeys de l'hôte parent en réglant passkeyRpId dans passkey-wallet.config.json (ou
PASSKEY_WALLET_PASSKEY_RP_ID) sur cet hôte. La valeur doit être le nom d'hôte courant ou l'un de ses domaines parents. pnpm dev local-organigram le fait pour
wallet.organigram.ai (voir Exécuter votre propre portefeuille).
Le portefeuille envoie une Content-Security-Policy qui interdit les scripts tiers et toute intégration de l'origine du portefeuille dans un cadre.
Le coffre à passkeys dépend de l'extension WebAuthn prf . Les navigateurs ou gestionnaires de mots de passe qui ne renvoient pas de sortie PRF ne peuvent pas déverrouiller le coffre chiffré.
Les applications doivent proposer une solution de repli claire quand PRF n'est pas disponible :
Organigram Passkey Wallet n'est pas un framework de smart accounts. Il ne nécessite ni infrastructure 4337, ni paymasters, ni bundlers, ni registres de modules, ni déploiements par chaîne.
Ce n'est pas un portefeuille custodial. Le serveur ne reçoit jamais la phrase de récupération ni la clé privée en clair.
Ce n'est pas un service de portefeuille hébergé. Le paquet est open source ; l'application hôte gère la persistance, l'authentification et la politique de sauvegarde.
Il ne remplace pas les portefeuilles matériels pour les conservations exigeant un haut niveau de garantie. Il est conçu pour offrir l'expérience web grand public la plus sûre possible, tout en restant portable et compatible EVM.
MIT
Les applications atteignent le portefeuille via createOrganigramRemotePasskeyWallet(), un portefeuille RainbowKit dont le connecteur wagmi ouvre le portefeuille dans une fenêtre popup. Chaque connexion, signature, transaction ou opération de chiffrement est une requête que l'utilisateur approuve dans la popup. Les applications échangent requêtes et réponses avec la popup via postMessage, et n'acceptent que les réponses provenant de l'origine du portefeuille et de sa copie locale. Les signatures sont vérifiées par rapport à l'adresse et à la chaîne connectées avant d'atteindre l'application. Les clés privées ne quittent jamais l'origine du portefeuille.
Entrée de createOrganigramRemotePasskeyWallet().
export type CreateOrganigramRemotePasskeyWalletInput = { walletOrigin?: string; requestConnect?: RemoteRequestConnect; requestPersonalSign?: RemoteRequestPersonalSign; requestSignTypedData?: RemoteRequestSignTypedData; requestSendTransaction?: RemoteRequestSendTransaction;};
Un connecteur wagmi, identifié par son id.
export type HydrateOrganigramRemoteWalletConnectionConnector = { id: string;};
Une adresse déjà connue de l'application, par exemple par sa session.
export type HydrateOrganigramRemoteWalletConnectionInput = { address: `0x${string}`; chainId?: number;};
Entrée de hydrateOrganigramRemoteWalletConnection().
export type HydrateOrganigramRemoteWalletConnectionOptions<TConnector extends HydrateOrganigramRemoteWalletConnectionConnector> = HydrateOrganigramRemoteWalletConnectionInput & { connectors: readonly TConnector[]; connectAsync: (input: { connector: TConnector; }) => Promise<unknown>; defaultChainId?: number;};
Une connexion au portefeuille mémorisée dans le stockage local de l'application.
Elle ne contient que l'adresse publique et la chaîne, jamais de clé : chaque signature est toujours demandée à l'utilisateur dans la popup du portefeuille.
export type OrganigramRemotePasskeyWalletConnection = { version: 1; address: `0x${string}`; chainId: number; connectedAt: string;};
Ajoute un contexte purement informatif aux prochaines approbations du portefeuille. Une application peut ainsi indiquer au portefeuille qu'une même action de l'utilisateur nécessite plusieurs signatures, sans élargir aucune approbation ni modifier son contenu signé.
beginOrganigramWalletApprovalSequence: (input: { count: number; label?: string;}) => (() => void)
Oublier la connexion mémorisée au portefeuille.
clearOrganigramRemotePasskeyWalletConnection: () => void
Créer le portefeuille RainbowKit du passkey wallet, qui ouvre le portefeuille dans une popup.
Le connecteur expose un fournisseur EIP-1193. Les demandes de compte et de signature ouvrent la popup du portefeuille, et chaque signature est vérifiée par rapport à l'adresse et à la chaîne connectées. Les autres requêtes JSON-RPC vont à l'URL RPC par défaut de la chaîne active.
const connectors = connectorsForWallets( [{ groupName: 'Organigram', wallets: [() => createOrganigramRemotePasskeyWallet()] }], { appName: 'My app', projectId })
createOrganigramRemotePasskeyWallet: (input?: CreateOrganigramRemotePasskeyWalletInput) => Wallet
Paramètres
| Nom | Type | Description |
|---|---|---|
input | CreateOrganigramRemotePasskeyWalletInput | L'origine du portefeuille, et les remplacements de ses requêtes. |
Lire la connexion mémorisée au portefeuille.
getOrganigramRemotePasskeyWalletConnection: () => OrganigramRemotePasskeyWalletConnection | null
Retourne
| Type | Description |
|---|---|
OrganigramRemotePasskeyWalletConnection | null | La connexion, ou null si aucune n'est valide. |
Connecter wagmi au portefeuille pour une adresse que l'application connaît déjà, sans ouvrir la popup du portefeuille.
Mémorise la connexion, puis connecte le connecteur du portefeuille, qui la restaure. Si la connexion échoue, elle est oubliée.
hydrateOrganigramRemoteWalletConnection: <TConnector extends HydrateOrganigramRemoteWalletConnectionConnector>(input: HydrateOrganigramRemoteWalletConnectionOptions<TConnector>) => Promise<void>
Mémoriser une connexion au portefeuille dans le stockage local.
rememberOrganigramRemotePasskeyWalletConnection: (input: { address: `0x${string}`; chainId: number;}) => void
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: `0x${string}`; chainId: number; } | L'adresse et la chaîne connectées. |
Identifiant du connecteur wagmi du portefeuille, organigramPasskeyWalletId.
const organigramRemotePasskeyWalletId = "organigram-passkeys"
Entrée de requestPasskeyWalletConnect().
export type PasskeyWalletConnectPopupInput = PasskeyWalletRemotePopupInput;
Une requête pour connecter une application au portefeuille, qui répond avec l'adresse choisie.
export type PasskeyWalletConnectRequest = PasskeyWalletRemoteRequestBase & { type: typeof passkeyWalletConnectType;};
La réponse à une requête de connexion, avec l'adresse choisie par l'utilisateur.
export type PasskeyWalletConnectResult = PasskeyWalletRemoteResultBase & { type: typeof passkeyWalletConnectResultType;};
Une requête pour déchiffrer un texte chiffré pour l'origine de l'application.
export type PasskeyWalletDecryptPayloadRequest = PasskeyWalletRemoteRequestBase & { type: typeof passkeyWalletDecryptPayloadType; address: `0x${string}`; encryptedPayload: WalletEncryptedPayload;};
La réponse à une requête de déchiffrement.
export type PasskeyWalletDecryptPayloadResult = PasskeyWalletRemoteResultBase & { type: typeof passkeyWalletDecryptPayloadResultType; plaintext: string;};
Une requête pour chiffrer un texte avec la clé de chiffrement du portefeuille, pour l'origine de l'application.
export type PasskeyWalletEncryptPayloadRequest = PasskeyWalletRemoteRequestBase & { type: typeof passkeyWalletEncryptPayloadType; address: `0x${string}`; plaintext: string;};
La réponse à une requête de chiffrement.
export type PasskeyWalletEncryptPayloadResult = PasskeyWalletRemoteResultBase & { type: typeof passkeyWalletEncryptPayloadResultType; encryptedPayload: WalletEncryptedPayload;};
La réponse à une requête que le portefeuille n'a pas pu traiter.
export type PasskeyWalletRemoteErrorResult = Omit<PasskeyWalletRemoteResultBase, 'address'> & { type: typeof passkeyWalletRemoteErrorResultType; address?: undefined; error: string;};
Entrée commune des requêtes adressées à la popup du portefeuille.
export type PasskeyWalletRemotePopupInput = { walletOrigin?: string; appOrigin?: string; chainId: number; requestId?: string; requestedAt?: string; approvalStep?: number; approvalCount?: number; approvalLabel?: string;};
Une requête qu'une application peut envoyer au portefeuille.
export type PasskeyWalletRemoteRequest = PasskeyWalletConnectRequest | PasskeyWalletSignMessageRequest | PasskeyWalletSignTypedDataRequest | PasskeyWalletSendTransactionRequest | PasskeyWalletEncryptPayloadRequest | PasskeyWalletDecryptPayloadRequest;
Le message par lequel une application transmet une requête à la popup du portefeuille.
export type PasskeyWalletRemoteRequestPayloadMessage = { type: typeof passkeyWalletRemoteRequestPayloadType; version: 1; request: PasskeyWalletRemoteRequest;};
Types des requêtes qu'une application peut envoyer au portefeuille.
export type PasskeyWalletRemoteRequestType = typeof passkeyWalletConnectType | typeof passkeyWalletSignMessageType | typeof passkeyWalletSignTypedDataType | typeof passkeyWalletSendTransactionType | typeof passkeyWalletEncryptPayloadType | typeof passkeyWalletDecryptPayloadType;
Une réponse du portefeuille à une requête.
export type PasskeyWalletRemoteResult = PasskeyWalletConnectResult | PasskeyWalletSignMessageResult | PasskeyWalletSignTypedDataResult | PasskeyWalletSendTransactionResult | PasskeyWalletEncryptPayloadResult | PasskeyWalletDecryptPayloadResult | PasskeyWalletRemoteErrorResult;
Une requête pour signer et envoyer une transaction.
export type PasskeyWalletSendTransactionRequest = PasskeyWalletRemoteRequestBase & { type: typeof passkeyWalletSendTransactionType; address: `0x${string}`; transaction: PasskeyWalletTransaction;};
La réponse à une requête d'envoi de transaction.
export type PasskeyWalletSendTransactionResult = PasskeyWalletRemoteResultBase & { type: typeof passkeyWalletSendTransactionResultType; transactionHash: `0x${string}`;};
Entrée de requestPasskeyWalletSignMessage().
export type PasskeyWalletSignMessagePopupInput = PasskeyWalletRemotePopupInput & { address: `0x${string}`; message: string;};
Une requête pour signer un message avec EIP-191 personal_sign.
export type PasskeyWalletSignMessageRequest = PasskeyWalletRemoteRequestBase & { type: typeof passkeyWalletSignMessageType; address: `0x${string}`; message: string;};
La réponse à une requête de signature de message.
export type PasskeyWalletSignMessageResult = PasskeyWalletRemoteResultBase & { type: typeof passkeyWalletSignMessageResultType; message: string; signature: `0x${string}`;};
Entrée d'une requête de signature de données typées.
export type PasskeyWalletSignTypedDataPopupInput = PasskeyWalletRemotePopupInput & { address: `0x${string}`; typedData: PasskeyWalletTypedData;};
Une requête pour signer des données typées EIP-712.
export type PasskeyWalletSignTypedDataRequest = PasskeyWalletRemoteRequestBase & { type: typeof passkeyWalletSignTypedDataType; address: `0x${string}`; typedData: PasskeyWalletTypedData;};
La réponse à une requête de signature de données typées.
export type PasskeyWalletSignTypedDataResult = PasskeyWalletRemoteResultBase & { type: typeof passkeyWalletSignTypedDataResultType; typedData: PasskeyWalletTypedData; signature: `0x${string}`;};
Une transaction à envoyer, avec des quantités en hexadécimal.
export type PasskeyWalletTransaction = { from: `0x${string}`; to: `0x${string}`; data?: `0x${string}`; value?: `0x${string}`; gas?: `0x${string}`; gasPrice?: `0x${string}`; maxFeePerGas?: `0x${string}`; maxPriorityFeePerGas?: `0x${string}`; nonce?: `0x${string}`;};
Données typées EIP-712.
export type PasskeyWalletTypedData = { domain: Record<string, unknown>; types: Record<string, ReadonlyArray<{ name: string; type: string; }>>; primaryType: string; message: Record<string, unknown>;};
Vérifier qu'un message signé provient de l'adresse et de la chaîne attendues.
Retrouve le signataire à partir de la signature, afin qu'une réponse falsifiée soit rejetée. Cela ne fonctionne que pour les signatures d'EOA, que produit le portefeuille.
assertPasskeyWalletSignMessageResult: (input: { result: PasskeyWalletSignMessageResult; address: `0x${string}`; chainId: number; message: string;}) => Promise<void>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { result: PasskeyWalletSignMessageResult; address: `0x${string}`; chainId: number; message: string; } | La réponse, et l'adresse, la chaîne et le message de la requête. |
Vérifier que des données typées signées proviennent de l'adresse et de la chaîne attendues.
Retrouve le signataire à partir de la signature, afin qu'une réponse falsifiée soit rejetée.
assertPasskeyWalletSignTypedDataResult: (input: { result: PasskeyWalletSignTypedDataResult; address: `0x${string}`; chainId: number; typedData: PasskeyWalletTypedData;}) => Promise<void>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { result: PasskeyWalletSignTypedDataResult; address: `0x${string}`; chainId: number; typedData: PasskeyWalletTypedData; } | La réponse, et l'adresse, la chaîne et les données typées de la requête. |
Construire l'URL de la popup du portefeuille pour une requête.
Toute requête autre que la connexion est ensuite transmise par postMessage. Le portefeuille lit l'origine demandeuse dans le MessageEvent authentifié par le navigateur, au lieu de faire confiance au appOrigin écrit dans l'URL, et aucun message, aucune transaction ni aucun secret ne se retrouve dans une URL.
buildPasskeyWalletRemotePopupUrl: (input: PasskeyWalletRemotePopupInput & { type: PasskeyWalletRemoteRequestType; address?: `0x${string}`;}) => URL
Paramètres
| Nom | Type | Description |
|---|---|---|
input | PasskeyWalletRemotePopupInput & { type: PasskeyWalletRemoteRequestType; address?: `0x${string}`; } | La requête, avec son type et son adresse. |
Vérifier qu'un message transmis est une requête valide au portefeuille.
Le domaine de la requête doit être l'hôte de son appOrigin. Le portefeuille doit encore comparer appOrigin à l'origine du MessageEvent, que le navigateur authentifie.
isPasskeyWalletRemoteRequestPayloadMessage: (value: unknown, expectedRequestId?: string) => value is PasskeyWalletRemoteRequestPayloadMessage
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | Les données du message. |
expectedRequestId | string | L'identifiant de la requête attendue, s'il est connu. |
Vérifier qu'une valeur est une transaction avec des adresses valides et des quantités hexadécimales.
isPasskeyWalletTransaction: (value: unknown) => value is PasskeyWalletTransaction
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | La valeur à vérifier. |
Lire et vérifier une requête à partir des paramètres d'URL de la popup du portefeuille.
Rejette les requêtes de chiffrement et de déchiffrement, qui doivent être transmises par postMessage, ainsi que les requêtes dont le domaine n'est pas l'hôte de leur appOrigin.
parsePasskeyWalletRemoteRequest: (params: URLSearchParams) => PasskeyWalletRemoteRequest
Paramètres
| Nom | Type | Description |
|---|---|---|
params | URLSearchParams | Les paramètres d'URL. |
Lire des données typées.
parsePasskeyWalletTypedData: (value: unknown) => PasskeyWalletTypedData
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | Les données typées, ou leur JSON. |
Demander au portefeuille, dans une popup, de connecter l'application.
requestPasskeyWalletConnect: (input: PasskeyWalletConnectPopupInput & { timeoutMs?: number;}) => Promise<PasskeyWalletConnectResult>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | PasskeyWalletConnectPopupInput & { timeoutMs?: number; } | La requête, et un délai d'expiration, 5 minutes par défaut. |
Retourne
| Type | Description |
|---|---|
Promise<PasskeyWalletConnectResult> | La réponse, avec l'adresse choisie par l'utilisateur. |
Demander au portefeuille, dans une popup, de déchiffrer un texte chiffré pour l'origine de l'application.
requestPasskeyWalletDecryptPayload: (input: PasskeyWalletRemotePopupInput & { address: `0x${string}`; encryptedPayload: WalletEncryptedPayload; timeoutMs?: number;}) => Promise<PasskeyWalletDecryptPayloadResult>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | PasskeyWalletRemotePopupInput & { address: `0x${string}`; encryptedPayload: WalletEncryptedPayload; timeoutMs?: number; } | La requête, l'adresse, le contenu chiffré et un délai d'expiration, 5 minutes par défaut. |
Retourne
| Type | Description |
|---|---|
Promise<PasskeyWalletDecryptPayloadResult> | La réponse, avec le texte déchiffré. |
Demander au portefeuille, dans une popup, de chiffrer un texte pour l'origine de l'application.
requestPasskeyWalletEncryptPayload: (input: PasskeyWalletRemotePopupInput & { address: `0x${string}`; plaintext: string; timeoutMs?: number;}) => Promise<PasskeyWalletEncryptPayloadResult>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | PasskeyWalletRemotePopupInput & { address: `0x${string}`; plaintext: string; timeoutMs?: number; } | La requête, l'adresse, le texte et un délai d'expiration, 5 minutes par défaut. |
Retourne
| Type | Description |
|---|---|
Promise<PasskeyWalletEncryptPayloadResult> | La réponse, avec le contenu chiffré. |
Demander au portefeuille, dans une popup, de signer un message.
La réponse est vérifiée avec assertPasskeyWalletSignMessageResult().
requestPasskeyWalletSignMessage: (input: PasskeyWalletSignMessagePopupInput & { timeoutMs?: number;}) => Promise<PasskeyWalletSignMessageResult>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | PasskeyWalletSignMessagePopupInput & { timeoutMs?: number; } | La requête, l'adresse, le message et un délai d'expiration, 5 minutes par défaut. |
Retourne
| Type | Description |
|---|---|
Promise<PasskeyWalletSignMessageResult> | La réponse, avec la signature. |
Sérialiser des données typées en JSON, en écrivant les bigints sous forme de chaînes décimales.
stringifyPasskeyWalletTypedData: (typedData: PasskeyWalletTypedData) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
typedData | PasskeyWalletTypedData | Les données typées. |
Type de la réponse à une requête de connexion.
const passkeyWalletConnectResultType = "organigram:wallet:connect-result"
Type d'une requête pour connecter une application au portefeuille.
const passkeyWalletConnectType = "organigram:wallet:connect"
Type de la réponse à une requête de déchiffrement.
const passkeyWalletDecryptPayloadResultType = "organigram:wallet:decrypt-payload-result"
Type d'une requête pour déchiffrer un texte avec la clé de chiffrement du portefeuille.
const passkeyWalletDecryptPayloadType = "organigram:wallet:decrypt-payload"
Type de la réponse à une requête de chiffrement.
const passkeyWalletEncryptPayloadResultType = "organigram:wallet:encrypt-payload-result"
Type d'une requête pour chiffrer un texte avec la clé de chiffrement du portefeuille.
const passkeyWalletEncryptPayloadType = "organigram:wallet:encrypt-payload"
Type de la réponse à une requête que le portefeuille n'a pas pu traiter.
const passkeyWalletRemoteErrorResultType = "organigram:wallet:remote-error"
Type du message par lequel une application transmet une requête à la popup du portefeuille.
const passkeyWalletRemoteRequestPayloadType = "organigram:wallet:request-payload"
Type de la réponse à une requête d'envoi de transaction.
const passkeyWalletSendTransactionResultType = "organigram:wallet:send-transaction-result"
Type d'une requête d'envoi de transaction.
const passkeyWalletSendTransactionType = "organigram:wallet:send-transaction"
Type de la réponse à une requête de signature de message.
const passkeyWalletSignMessageResultType = "organigram:wallet:sign-message-result"
Type d'une requête de signature de message.
const passkeyWalletSignMessageType = "organigram:wallet:sign-message"
Type de la réponse à une requête de signature de données typées.
const passkeyWalletSignTypedDataResultType = "organigram:wallet:sign-typed-data-result"
Type d'une requête de signature de données typées EIP-712.
const passkeyWalletSignTypedDataType = "organigram:wallet:sign-typed-data"
Les origines dont une application qui attend walletOrigin accepte les messages.
getAcceptedWalletOrigins: (walletOrigin: string) => string[]
La copie locale de walletOrigin, s'il en a une.
getLocalWalletOrigin: (walletOrigin: string) => string | null
Seul un sous-domaine HTTPS de l'hôte du portefeuille peut déverrouiller ses passkeys.
isLocalWalletOriginOf: (localWalletOrigin: string, walletOrigin: string) => boolean
Envoie un message à la popup du portefeuille, quelle que soit l'origine acceptée qu'elle affiche : le navigateur ne le remet qu'à celle sur laquelle se trouve la popup.
postToWalletPopup: (popup: Window, message: unknown, walletOrigin: string) => void
Mémorise laquelle des origines acceptées a répondu pour walletOrigin.
rememberWalletOrigin: (walletOrigin: string, answeringOrigin: string) => void
Ouvre les requêtes sur la copie locale une fois qu'elle a répondu sur cet appareil, afin que le portefeuille officiel ne soit plus chargé du tout.
toPreferredWalletUrl: (url: URL) => URL
Ramène la popup sur le portefeuille quand sa copie locale ne répond pas, par exemple parce qu'elle n'est pas lancée. Renvoie la fonction de nettoyage.
watchLocalWalletPopup: (input: { popup: Window; popupUrl: URL; walletOrigin: string; requestId: string; timeoutMs?: number;}) => (() => void)
Demande à un portefeuille de traiter lui-même une requête.
const localWalletOptOutParam = "localWallet"
Origine de la copie locale du portefeuille officiel.
Un portefeuille peut avoir une copie locale : le même portefeuille exécuté sur la machine de l'utilisateur, servi sous un sous-domaine de l'hôte du portefeuille, afin qu'il déverrouille les mêmes passkeys. Une application qui fait confiance au portefeuille fait alors aussi confiance à cette copie. La copie du portefeuille officiel est pnpm dev local-organigram; un autre déploiement déclare la sienne via NEXT_PUBLIC_ORGANIGRAM_PASSKEY_WALLET_LOCAL_URL.
const officialLocalWalletOrigin = "https://local.wallet.organigram.ai:3002"
Origine du passkey wallet officiel d'Organigram.
const officialWalletOrigin = "https://wallet.organigram.ai"
Transmis par un portefeuille avant qu'il ne confie une requête à sa copie locale.
const passkeyWalletLocalHandoffType = "organigram:wallet:local-handoff"
Transmis par la page de requête de la copie locale dès son chargement.
const passkeyWalletReadyType = "organigram:wallet:ready"
Les utilisateurs se connectent à une application avec Sign-In with Ethereum. L'application émet un message avec un nonce venant de son serveur, le portefeuille le signe dans une popup, et le serveur vérifie la signature, le domaine et le nonce avant d'ouvrir une session. Avec NextAuth, signInWithPasskeyWallet() exécute tout le parcours dans le navigateur, et authorizePasskeyWalletCredentials() vérifie le résultat dans un fournisseur d'identifiants.
Entrée d'une requête de connexion via la popup du portefeuille.
export type PasskeyWalletPopupInput = { walletOrigin?: string; appOrigin?: string; nonce: string; chainId: number; requestId?: string; requestedAt?: string; popup?: Window | null;};
Un message transmis par le portefeuille à l'application qui l'a ouvert quand l'utilisateur révoque la session de cette application.
export type PasskeyWalletStackSessionChangedMessage = { type: typeof passkeyWalletStackSessionChangedType; version: 1; event: 'revoked'; appOrigin: string; address: `0x${string}` | null;};
Entrée de signInWithPasskeyWallet().
export type SignInWithPasskeyWalletInput = { chainId?: number; walletOrigin?: string; getCsrfToken: () => Promise<string | null | undefined>; requestWalletSignIn?: (input: WalletSignInInput) => Promise<PasskeyWalletSignInResult>; submitCredentials?: SubmitCredentials;};
Construire l'URL de la popup du portefeuille pour une requête de connexion, avec l'URL de défi /api/auth/wallet/challenge de l'application.
buildPasskeyWalletSignInPopupUrl: (input: PasskeyWalletPopupInput) => URL
Paramètres
| Nom | Type | Description |
|---|---|---|
input | PasskeyWalletPopupInput | La requête de connexion. |
Créer un message de changement de session.
createPasskeyWalletStackSessionChangedMessage: (input: { event: "revoked"; appOrigin: string; address?: `0x${string}` | null;}) => PasskeyWalletStackSessionChangedMessage
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { event: "revoked"; appOrigin: string; address?: `0x${string}` | null; } | L'événement, l'origine de l'application et l'adresse de la session. |
Signaler à NextAuth, dans l'onglet courant, que la session a changé, afin qu'il la recharge.
notifyCurrentTabNextAuthSessionChanged: () => void
Transmettre un message de changement de session à la fenêtre qui a ouvert le portefeuille.
notifyPasskeyWalletStackSessionChanged: (input: { event: "revoked"; appOrigin: string; address?: `0x${string}` | null; targetOrigin?: string;}) => void
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { event: "revoked"; appOrigin: string; address?: `0x${string}` | null; targetOrigin?: string; } | L'événement, l'origine de l'application, l'adresse de la session et l'origine à laquelle transmettre, par défaut celle de l'application. |
Lire un message de changement de session.
Vérifiez aussi l'origine du MessageEvent qui le transporte : ne faites confiance qu'aux messages du portefeuille.
parsePasskeyWalletStackSessionChangedMessage: (value: unknown) => PasskeyWalletStackSessionChangedMessage | null
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | Les données du message. |
Retourne
| Type | Description |
|---|---|
PasskeyWalletStackSessionChangedMessage | null | Le message, ou null si elle est invalide. |
Demander au portefeuille, dans une popup, de signer un message Sign-In with Ethereum pour l'application.
N'accepte que les réponses de l'origine du portefeuille et de sa copie locale, pour cette requête. Le résultat n'est pas vérifié : le serveur doit le vérifier avec verifyPasskeyWalletSiwe().
requestPasskeyWalletSignIn: (input: PasskeyWalletPopupInput & { timeoutMs?: number;}) => Promise<PasskeyWalletSignInResult>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | PasskeyWalletPopupInput & { timeoutMs?: number; } | La requête de connexion, et un délai d'expiration, 5 minutes par défaut. |
Retourne
| Type | Description |
|---|---|
Promise<PasskeyWalletSignInResult> | Le message signé. |
Se connecter à une application NextAuth avec le portefeuille.
Ouvre la popup du portefeuille, utilise le jeton CSRF comme nonce du message Sign-In with Ethereum, et soumet le message signé au fournisseur d'identifiants NextAuth, qui le vérifie avec authorizePasskeyWalletCredentials().
import { getCsrfToken } from 'next-auth/react'await signInWithPasskeyWallet({ getCsrfToken })
signInWithPasskeyWallet: (input: SignInWithPasskeyWalletInput) => Promise<PasskeyWalletSignInResult>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | SignInWithPasskeyWalletInput | La fonction d'obtention du jeton CSRF, la chaîne et l'origine du portefeuille. |
Retourne
| Type | Description |
|---|---|
Promise<PasskeyWalletSignInResult> | Le message signé. |
Type du message signalant à une application que sa session a changé dans le portefeuille.
const passkeyWalletStackSessionChangedType = "organigram:wallet:stack-session-changed"
Soumettre un message signé au callback d'identifiants NextAuth de l'application, à /api/auth/callback/credentials.
const submitPasskeyWalletCredentials: SubmitCredentials
Entrée de authorizePasskeyWalletCredentials().
export type AuthorizePasskeyWalletCredentialsInput = { credentials: PasskeyWalletNextAuthCredentials | undefined; domain: string; nonce: string | null | undefined; chain?: Chain; transportUrl: string; transportOptions?: Parameters<typeof import('viem').http>[1];};
Identifiants soumis au fournisseur d'identifiants NextAuth.
export type PasskeyWalletNextAuthCredentials = { message?: unknown; signature?: unknown; csrfToken?: unknown;};
Vérifier les identifiants soumis à un fournisseur d'identifiants NextAuth par signInWithPasskeyWallet().
Rejette les identifiants sans message, signature ou nonce, puis les vérifie avec verifyPasskeyWalletSiwe(). Le nonce est le jeton CSRF de la session, que signInWithPasskeyWallet() place dans le message.
CredentialsProvider({ credentials: { message: {}, signature: {} }, authorize: async credentials => await authorizePasskeyWalletCredentials({ credentials, domain: 'app.example.com', nonce: csrfToken, transportUrl: rpcUrl })})
authorizePasskeyWalletCredentials: (input: AuthorizePasskeyWalletCredentialsInput) => Promise<PasskeyWalletVerifiedSiwe | null>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | AuthorizePasskeyWalletCredentialsInput | Les identifiants, le domaine et le nonce de l'application, et un point d'accès RPC. |
Retourne
| Type | Description |
|---|---|
Promise<PasskeyWalletVerifiedSiwe | null> | La connexion vérifiée, ou null. |
Un message Sign-In with Ethereum émis par une application pour que le portefeuille le signe.
export type PasskeyWalletChallenge = { domain: string; nonce: string; issuedAt: string; expiresAt: string; message: string;};
Un message Sign-In with Ethereum vérifié.
export type PasskeyWalletVerifiedSiwe = { address: `0x${string}`; chainId: number; domain: string; uri: string; nonce: string; encryptionPublicKeyResource: WalletEncryptionPublicKeySiweResource | null;};
Entrée de verifyPasskeyWalletSiwe().
export type PasskeyWalletVerifySiweInput = { message: string; signature: Hex; domain: string; nonce: string; chain?: Chain; transportUrl: string; transportOptions?: Parameters<typeof http>[1];};
Construire l'URL de la popup du portefeuille pour une requête de connexion.
buildPasskeyWalletPopupUrl: (input: { walletOrigin: string; domain: string; challengeUrl: string; requestId?: string; requestedAt?: string; returnUrl?: string;}) => URL
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { walletOrigin: string; domain: string; challengeUrl: string; requestId?: string; requestedAt?: string; returnUrl?: string; } | L'origine du portefeuille, le domaine de l'application, son URL de défi, et éventuellement l'identifiant de la requête, la date et l'URL de retour. |
Créer un message Sign-In with Ethereum pour une adresse, valable 5 minutes.
Stockez le nonce sur le serveur, par exemple dans la session, et vérifiez-le avec verifyPasskeyWalletSiwe().
createPasskeyWalletChallenge: (input: { request: Request; address: `0x${string}`; chainId: number; encryptionPublicKeyResource?: string; nonce?: string; now?: Date; statement?: string; uri?: string;}) => PasskeyWalletChallenge
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { request: Request; address: `0x${string}`; chainId: number; encryptionPublicKeyResource?: string; nonce?: string; now?: Date; statement?: string; uri?: string; } | La requête, l'adresse et la chaîne, et éventuellement la ressource de clé publique issue de createWalletEncryptionPublicKeySiweResource(), un nonce, la date courante, une déclaration et l'URI de l'application, par défaut l'origine de la requête. |
Créer le manifeste d'une application, avec l'URL de défi /api/auth/wallet/challenge sur l'origine de la requête.
createPasskeyWalletManifest: (request: Request) => PasskeyWalletManifest
Paramètres
| Nom | Type | Description |
|---|---|---|
request | Request | La requête du manifeste. |
Lister les origines de portefeuille autorisées à appeler les points d'accès de connexion d'une application.
Autorise le portefeuille officiel et sa copie locale, le portefeuille configuré et sa copie locale, les autres origines configurées et, quand l'application tourne sur localhost, le portefeuille servi sur le port 3002 du même hôte.
getPasskeyWalletCorsAllowedOrigins: (input: { request: Request; walletUrl?: string; allowedOrigins?: string;}) => string[]
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { request: Request; walletUrl?: string; allowedOrigins?: string; } | La requête, l'URL du portefeuille configuré et les autres origines autorisées, séparées par des virgules. |
Obtenir l'origine d'une requête si c'est une origine de portefeuille autorisée.
getPasskeyWalletCorsOrigin: (input: { request: Request; walletUrl?: string; allowedOrigins?: string;}) => string | null
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { request: Request; walletUrl?: string; allowedOrigins?: string; } | La requête, l'URL du portefeuille configuré et les autres origines autorisées, séparées par des virgules. |
Retourne
| Type | Description |
|---|---|
string | null | L'origine, ou null. |
Obtenir l'origine publique d'une requête, à partir des en-têtes X-Forwarded-Host et X-Forwarded-Proto lorsqu'ils sont présents.
Les clients peuvent définir ces en-têtes. Ne vous fiez au résultat que derrière un proxy qui les écrase.
getPasskeyWalletRequestOrigin: (request: Request) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
request | Request | La requête. |
Vérifier si une origine fait partie d'une liste d'origines autorisées.
isWalletSignInOriginAllowed: (origin: string, allowedOrigins: readonly string[]) => boolean
Paramètres
| Nom | Type | Description |
|---|---|---|
origin | string | L'origine à vérifier. |
allowedOrigins | readonly string[] | Les origines autorisées. |
Vérifier un message Sign-In with Ethereum signé par le portefeuille.
Vérifie avec viem la signature, le domaine, le nonce et les dates de validité du message. Ne passez jamais un domaine ou un nonce vide : viem ignore alors leur vérification. Vérifiez que le nonce est celui que l'application a émis pour cette session, et ne l'utilisez qu'une fois.
const verified = await verifyPasskeyWalletSiwe({ message, signature, domain: 'app.example.com', nonce: session.nonce, transportUrl: rpcUrl})
verifyPasskeyWalletSiwe: (input: PasskeyWalletVerifySiweInput) => Promise<PasskeyWalletVerifiedSiwe | null>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | PasskeyWalletVerifySiweInput | Le message, la signature, le domaine et le nonce attendus, et un point d'accès RPC. |
Retourne
| Type | Description |
|---|---|
Promise<PasskeyWalletVerifiedSiwe | null> | La connexion vérifiée, ou null si le message est invalide. |
Ajouter à une réponse des en-têtes CORS avec identifiants, si la requête vient d'une origine de portefeuille autorisée.
withPasskeyWalletCorsHeaders: <Response extends { headers: Headers;}>(request: Request, response: Response, options?: { allowedMethods?: string; walletUrl?: string; allowedOrigins?: string;}) => Response
Paramètres
| Nom | Type | Description |
|---|---|---|
request | Request | La requête. |
response | Response | La réponse, renvoyée avec ses en-têtes modifiés. |
options | { allowedMethods?: string; walletUrl?: string; allowedOrigins?: string; } | Méthodes autorisées, GET, OPTIONS par défaut, l'URL du portefeuille configuré et les autres origines autorisées. |
La réponse du portefeuille à une requête qu'il n'a pas pu traiter.
export type PasskeyWalletErrorResult = { type: typeof passkeyWalletErrorType; version: 1; requestId: string; code: 'user_rejected' | 'challenge_unavailable' | 'domain_mismatch' | 'wallet_locked' | 'unsupported_origin' | 'internal_error'; message: string;};
Comment une application accepte les connexions avec le portefeuille.
export type PasskeyWalletManifest = { version: 1; domain: string; signInChallengeUrl: string; signInCompletionUrl?: string;};
Une requête de connexion à une application avec le portefeuille, lue depuis l'URL de la popup du portefeuille.
export type PasskeyWalletSignInRequest = { type: typeof passkeyWalletSignInType; version: 1; requestId: string; domain: string; challengeUrl: string; returnUrl?: string; requestedAt: string;};
La réponse du portefeuille à une requête de connexion : un message Sign-In with Ethereum signé.
export type PasskeyWalletSignInResult = { type: typeof passkeyWalletSignInResultType; version: 1; requestId: string; domain: string; address: `0x${string}`; message: string; signature: `0x${string}`; completedAt: string;};
Vérifier qu'un message Sign-In with Ethereum est destiné au domaine attendu, avant de le signer.
assertSignInDomainMatches: (message: string, expectedDomain: string) => void
Paramètres
| Nom | Type | Description |
|---|---|---|
message | string | Le message. |
expectedDomain | string | Le domaine de la requête. |
Lire et vérifier une requête de connexion à partir des paramètres d'URL de la popup du portefeuille.
L'URL de défi doit utiliser HTTPS et appartenir au domaine demandé ou à l'un de ses sous-domaines, et l'URL de retour doit utiliser HTTPS, afin que le portefeuille ne signe que des messages récupérés auprès de l'application qui les demande.
parsePasskeyWalletSignInRequest: (params: URLSearchParams) => PasskeyWalletSignInRequest
Paramètres
| Nom | Type | Description |
|---|---|---|
params | URLSearchParams | Les paramètres d'URL. |
Lire le domaine d'un message Sign-In with Ethereum dans sa première ligne.
resolveSiweDomain: (message: string) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
message | string | Le message. |
Vérifier le manifeste d'une application.
Le domaine du manifeste doit être l'hôte qui le sert, et ses URL doivent utiliser HTTPS et appartenir à ce domaine ou à ses sous-domaines.
validatePasskeyWalletManifest: (manifest: unknown, servingHost: string) => PasskeyWalletManifest
Paramètres
| Nom | Type | Description |
|---|---|---|
manifest | unknown | Le manifeste, analysé depuis le JSON. |
servingHost | string | L'hôte depuis lequel le manifeste a été récupéré. |
Type du message répondant à une requête que le portefeuille n'a pas pu traiter.
const passkeyWalletErrorType = "organigram:wallet:error"
Type du message répondant à une requête de connexion.
const passkeyWalletSignInResultType = "organigram:wallet:sign-in-result"
Type d'une requête de connexion au portefeuille.
const passkeyWalletSignInType = "organigram:wallet:sign-in"
Le portefeuille est un compte Ethereum standard dérivé d'une phrase de récupération BIP-39. La phrase de récupération est chiffrée dans un coffre avec AES-256-GCM, sous une clé dérivée de la sortie PRF d'une passkey WebAuthn, afin que seule cette passkey puisse la déchiffrer. Un portefeuille peut avoir plusieurs passkeys, chacune avec son propre coffre. Ces fonctions s'exécutent dans l'application du portefeuille : un portefeuille déverrouillé garde en mémoire la phrase de récupération et les clés, ne l'y gardez donc que le temps nécessaire, et ne le stockez, ne l'envoyez ni ne le journalisez jamais.
Les secrets chiffrés dans un coffre à passkey.
Contient la phrase de récupération en clair : ne la stockez, ne l'envoyez ni ne la journalisez jamais hors d'une enveloppe chiffrée.
export type BrowserPasskeyWalletVaultPayload = { version: 1; recoveryPhrase: string; walletEncryptionKey?: WalletEncryptionKeyPairPayload;};
Une passkey à évaluer avec son sel PRF.
export type PasskeyPrfCredential = { credentialId: string; transports?: string[]; prfSalt: string;};
Créer le contenu d'un nouveau coffre, avec une nouvelle paire de clés de chiffrement du portefeuille.
createBrowserPasskeyWalletVaultPayload: (recoveryPhrase: string) => Promise<BrowserPasskeyWalletVaultPayload>
Paramètres
| Nom | Type | Description |
|---|---|---|
recoveryPhrase | string | La phrase de récupération du portefeuille. |
Générer une nouvelle phrase de récupération BIP-39 anglaise de 12 mots.
createGeneratedRecoveryPhrase: () => string
Déchiffrer une enveloppe de coffre avec la sortie PRF de sa passkey.
Ne met pas à zéro la sortie PRF, afin que l'appelant puisse essayer plusieurs enveloppes avec. Mettez-la à zéro une fois terminé.
decryptVaultPayloadWithPrfOutput: (input: { envelope: PasskeyVaultEnvelopeData; prfOutput: Uint8Array;}) => Promise<BrowserPasskeyWalletVaultPayload>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { envelope: PasskeyVaultEnvelopeData; prfOutput: Uint8Array; } | L'enveloppe et la sortie PRF. |
Passer un portefeuille déverrouillé sur un autre de ses comptes.
derivePasskeyWalletAccount: (input: { wallet: UnlockedPasskeyWallet; account: StoredVaultAccount;}) => UnlockedPasskeyWallet
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { wallet: UnlockedPasskeyWallet; account: StoredVaultAccount; } | Le portefeuille déverrouillé et le compte à sélectionner. |
Dériver d'une phrase de récupération le compte d'un index d'adresse.
deriveStoredVaultAccount: (input: { recoveryPhrase: string; addressIndex: number; name: string;}) => StoredVaultAccount
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { recoveryPhrase: string; addressIndex: number; name: string; } | La phrase de récupération, l'index d'adresse et le nom du compte, Account <index + 1> par défaut. |
Obtenir le chemin de dérivation Ethereum BIP-44 d'un index d'adresse.
getDerivationPath: (addressIndex: number) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
addressIndex | number | L'index d'adresse. |
Encoder un message UTF-8 en hexadécimal, comme le transportent les requêtes personal_sign .
hexEncodeMessage: (message: string) => `0x${string}`
Paramètres
| Nom | Type | Description |
|---|---|---|
message | string | Le message. |
Lire le contenu déchiffré d'un coffre.
parseBrowserPasskeyWalletVaultPayload: (plaintext: string) => BrowserPasskeyWalletVaultPayload
Paramètres
| Nom | Type | Description |
|---|---|---|
plaintext | string | Le contenu déchiffré, en JSON. |
Créer une autre passkey capable de déverrouiller un portefeuille déverrouillé, par exemple comme passkey de secours.
registerAdditionalBrowserPasskeyVault: (input: { wallet: UnlockedPasskeyWallet; name: string; accounts: StoredVaultAccount[]; rpId?: string; rpName?: string;}) => Promise<{ record: StoredVaultRecord; wallet: UnlockedPasskeyWallet;}>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { wallet: UnlockedPasskeyWallet; name: string; accounts: StoredVaultAccount[]; rpId?: string; rpName?: string; } | Le portefeuille déverrouillé, le nom de la passkey, les comptes qu'elle déverrouille et la partie de confiance WebAuthn. |
Retourne
| Type | Description |
|---|---|
Promise<{ record: StoredVaultRecord; wallet: UnlockedPasskeyWallet; }> | Le nouvel enregistrement de coffre et le portefeuille, désormais rattaché à la nouvelle passkey. |
Créer une passkey et un coffre qui chiffre avec elle une phrase de récupération.
Demande au navigateur de créer une passkey détectable avec vérification de l'utilisateur et l'extension PRF. La phrase de récupération est chiffrée avec une clé dérivée de la sortie PRF, qui est ensuite mise à zéro. Stockez l'enregistrement renvoyé, qui ne contient aucun secret en clair, et ne gardez le portefeuille déverrouillé qu'en mémoire.
const { record, wallet } = await registerBrowserPasskeyVault({ recoveryPhrase: createGeneratedRecoveryPhrase(), name: 'My wallet'})
registerBrowserPasskeyVault: (input: { recoveryPhrase: string; name: string; rpId?: string; rpName?: string;}) => Promise<{ record: StoredVaultRecord; wallet: UnlockedPasskeyWallet;}>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { recoveryPhrase: string; name: string; rpId?: string; rpName?: string; } | La phrase de récupération, le nom du portefeuille, l'identifiant de la partie de confiance WebAuthn, par défaut le nom d'hôte courant, et le nom de la partie de confiance. |
Retourne
| Type | Description |
|---|---|
Promise<{ record: StoredVaultRecord; wallet: UnlockedPasskeyWallet; }> | L'enregistrement de coffre et le portefeuille déverrouillé, sur son premier compte. |
Exécute une assertion avec vérification de l'utilisateur, limitée aux passkeys données, chacune évaluée avec son propre sel PRF, et renvoie la sortie PRF de la passkey choisie par la personne. L'appelant est responsable de la sortie PRF renvoyée et doit la mettre à zéro une fois sa clé dérivée.
requestPasskeyPrfOutput: (input: { credentials: PasskeyPrfCredential[]; rpId?: string;}) => Promise<{ credentialId: string; prfOutput: Uint8Array;}>
Signer un message avec EIP-191 personal_sign.
signPersonalMessage: (input: { wallet: UnlockedPasskeyWallet; message: string;}) => Promise<`0x${string}`>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { wallet: UnlockedPasskeyWallet; message: string; } | Le portefeuille déverrouillé et le message. |
Signer des données typées EIP-712.
signTypedDataMessage: (input: { wallet: UnlockedPasskeyWallet; typedData: PasskeyWalletTypedData;}) => Promise<`0x${string}`>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { wallet: UnlockedPasskeyWallet; typedData: PasskeyWalletTypedData; } | Le portefeuille déverrouillé et les données typées. |
Déverrouiller un portefeuille avec l'une des passkeys de ses coffres.
Demande à l'utilisateur de choisir l'une des passkeys des enregistrements, avec vérification de l'utilisateur. Les coffres de cette passkey sont essayés tour à tour, et le premier dont la phrase de récupération dérive l'adresse de son enregistrement est déverrouillé. La sortie PRF est mise à zéro.
const { wallet } = await unlockBrowserPasskeyVault({ records })const signature = await signPersonalMessage({ wallet, message: 'Hello' })
unlockBrowserPasskeyVault: (input: { records: StoredVaultRecord[]; rpId?: string;}) => Promise<{ record: StoredVaultRecord; wallet: UnlockedPasskeyWallet;}>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { records: StoredVaultRecord[]; rpId?: string; } | Les enregistrements de coffres parmi lesquels choisir, et l'identifiant de la partie de confiance WebAuthn, par défaut le nom d'hôte courant. |
Retourne
| Type | Description |
|---|---|
Promise<{ record: StoredVaultRecord; wallet: UnlockedPasskeyWallet; }> | L'enregistrement déverrouillé et le portefeuille, sur le premier compte de l'enregistrement. |
Déverrouiller un coffre et le rechiffrer avec une autre paire de clés de chiffrement du portefeuille.
Demande une passkey à l'utilisateur, et conserve le sel PRF du coffre. Stockez l'enregistrement renvoyé à la place de l'ancien.
updateStaticPasskeyVaultEncryptionKey: (input: { records: StoredVaultRecord[]; walletEncryptionKey: WalletEncryptionKeyPairPayload; rpId?: string;}) => Promise<{ record: StoredVaultRecord; wallet: UnlockedPasskeyWallet;}>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { records: StoredVaultRecord[]; walletEncryptionKey: WalletEncryptionKeyPairPayload; rpId?: string; } | Les enregistrements de coffres parmi lesquels choisir, la nouvelle paire de clés et l'identifiant de la partie de confiance WebAuthn. |
Retourne
| Type | Description |
|---|---|
Promise<{ record: StoredVaultRecord; wallet: UnlockedPasskeyWallet; }> | L'enregistrement rechiffré et le portefeuille déverrouillé. |
Un secret chiffré avec une clé dérivée d'une passkey, comme la phrase de récupération d'un portefeuille.
L'enveloppe ne contient aucun secret : elle peut être stockée n'importe où, car seule la passkey qui l'a créée peut la déchiffrer.
export type PasskeyVaultEnvelopeData = { algorithm: typeof passkeyVaultAlgorithm; keyVersion: typeof passkeyVaultKeyVersion; ciphertext: string; salt: string; prfSalt: string; nonce: string;};
Décoder du base64url sans remplissage.
N'accepte que du base64url canonique sans remplissage. Les décodeurs tolérants ignorent silencieusement les caractères inconnus : une valeur altérée pourrait sinon se décoder en d'autres octets que ceux qu'elle semble encoder.
base64UrlToBytes: (value: string) => Uint8Array
Paramètres
| Nom | Type | Description |
|---|---|---|
value | string | La valeur à décoder. |
Encoder des octets en base64url sans remplissage.
bytesToBase64Url: (bytes: Uint8Array) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
bytes | Uint8Array | Les octets à encoder. |
Déchiffrer le secret d'une enveloppe de coffre.
decryptPasskeyVaultSecret: (input: DecryptPasskeyVaultSecretInput) => Promise<string>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | ~DecryptPasskeyVaultSecretInput | L'enveloppe et la clé dérivée pour elle. |
Dériver la clé AES-GCM d'un coffre à partir de la sortie PRF d'une passkey.
La clé ne peut pas être exportée. Une copie de la sortie PRF faite pour l'import est ensuite mise à zéro, mais pas l'original : mettez-le à zéro dès que vous n'en avez plus besoin.
derivePasskeyVaultKey: (input: DerivePasskeyVaultKeyInput) => Promise<CryptoKey>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | ~DerivePasskeyVaultKeyInput | La sortie PRF de 32 octets, le sel de 32 octets du coffre et un info HKDF facultatif qui sépare les clés dérivées d'une même sortie PRF pour des usages différents. |
Chiffrer un secret avec une clé de coffre en une enveloppe de coffre.
encryptPasskeyVaultSecret: (input: EncryptPasskeyVaultSecretInput) => Promise<PasskeyVaultEnvelopeData>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | ~EncryptPasskeyVaultSecretInput | Le secret, la clé issue de derivePasskeyVaultKey(), le sel avec lequel elle a été dérivée, le sel PRF de 32 octets et un nonce facultatif de 12 octets, aléatoire par défaut. Ne réutilisez jamais un nonce avec la même clé. |
Obtenir la Web Crypto API de l'environnement.
getCrypto: () => Crypto
Vérifier qu'une valeur est du base64url canonique dont la longueur décodée passe un test.
hasBase64UrlByteLength: (value: unknown, isValidLength: (byteLength: number) => boolean) => boolean
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | La valeur à vérifier. |
isValidLength | (byteLength: number) => boolean | Test de la longueur décodée, en octets. |
Vérifier si une passkey nouvellement créée a activé l'extension PRF, dont le portefeuille a besoin pour dériver ses clés.
isPasskeyPrfSupported: (input: { credential: PrfSupportCredential | null;}) => Promise<boolean>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { credential: ~PrfSupportCredential | null; } | L'identifiant renvoyé par navigator.credentials.create(). |
Vérifier qu'une valeur est une enveloppe de coffre à passkey de l'algorithme et de la version de clé actuels, avec des sels, un nonce et un texte chiffré de longueurs valides.
isPasskeyVaultEnvelope: (value: unknown) => value is PasskeyVaultEnvelopeData
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | La valeur à vérifier. |
Générer des octets aléatoires cryptographiquement sûrs.
randomBytes: (length: number) => Uint8Array
Paramètres
| Nom | Type | Description |
|---|---|---|
length | number | Nombre d'octets. |
Copier les octets d'une vue dans un nouveau ArrayBuffer.
toArrayBuffer: (bytes: Uint8Array) => ArrayBuffer
Paramètres
| Nom | Type | Description |
|---|---|---|
bytes | Uint8Array | Les octets à copier. |
Algorithme des coffres à passkeys : AES-256-GCM avec une clé dérivée par HKDF-SHA-256 de la sortie PRF de la passkey.
const passkeyVaultAlgorithm = "AES-GCM-HKDF-SHA-256"
Version de la dérivation de clé des coffres à passkeys.
const passkeyVaultKeyVersion = 2
Décodeur UTF-8 partagé.
const textDecoder: TextDecoder
Encodeur UTF-8 partagé.
const textEncoder: TextEncoder
Événements émis par le fournisseur EIP-1193 du portefeuille.
export type PasskeyProviderEvent = 'accountsChanged' | 'chainChanged' | 'disconnect';
Écouteur d'un événement du fournisseur.
export type PasskeyProviderListener = (...args: unknown[]) => void;
L'adresse et la passkey d'un portefeuille nouvellement enregistré.
export type PasskeyRegistrationResult = { address: `0x${string}`; credentialId: string;};
Un portefeuille déverrouillé avec une passkey, prêt à signer.
Il garde en mémoire la phrase de récupération et les clés privées. Ne le gardez en mémoire que le temps nécessaire, et ne le stockez, ne l'envoyez ni ne le journalisez jamais.
export type UnlockedPasskeyWallet = { address: `0x${string}`; account: HDAccount; recoveryPhrase: string; walletEncryptionKey?: WalletEncryptionKeyPairPayload; credentialId: string;};
Chemin de l'icône du passkey wallet, relatif à l'application qui le sert.
const organigramPasskeyWalletIcon = "/png/logo-gradient.png"
Identifiant du connecteur du passkey wallet.
const organigramPasskeyWalletId = "organigram-passkeys"
Un enregistrement de coffre contient une enveloppe de coffre avec les informations publiques nécessaires pour la déverrouiller : les comptes, la passkey et son appareil. Les enregistrements ne contiennent aucun secret en clair, ils peuvent donc être stockés dans le navigateur ou exportés. Ces fonctions lisent, listent et mettent à jour les enregistrements.
Un compte d'un portefeuille, dérivé de sa phrase de récupération.
export type StoredVaultAccount = { address: `0x${string}`; name: string; addressIndex: number; derivationPath: string;};
Un coffre de portefeuille chiffré pour une passkey, avec les informations publiques nécessaires pour le déverrouiller.
Un portefeuille a un enregistrement par passkey capable de le déverrouiller. L'enregistrement ne contient aucun secret en clair : seule sa passkey peut déchiffrer l'enveloppe.
export type StoredVaultRecord = { version: 1; address: `0x${string}`; accounts: StoredVaultAccount[]; credentialId: string; rawCredentialId?: string; name: string; transports: string[]; passkeyDevice: { kind: 'macos' | 'ios' | 'ipados' | 'windows' | 'android' | 'linux' | 'security-key' | 'cross-device' | 'platform' | 'passkey'; label: string; }; createdAt: string; lastUsedAt: string | null; envelope: PasskeyVaultEnvelopeData;};
Une liste d'enregistrements de coffres, telle que stockée ou exportée.
export type VaultRegistry = { version: 1; vaults: StoredVaultRecord[];};
Ajouter un compte à chaque coffre du portefeuille qui contient un autre compte.
addAccountToVaultRecords: (input: { vaults: StoredVaultRecord[]; sourceAddress: `0x${string}`; account: StoredVaultAccount;}) => StoredVaultRecord[]
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { vaults: StoredVaultRecord[]; sourceAddress: `0x${string}`; account: StoredVaultAccount; } | Les enregistrements de coffres, un compte que le portefeuille contient déjà, et le compte à ajouter. |
Envelopper des enregistrements de coffres dans un registre.
createVaultRegistry: (vaults: StoredVaultRecord[]) => VaultRegistry
Paramètres
| Nom | Type | Description |
|---|---|---|
vaults | StoredVaultRecord[] | Les enregistrements de coffres. |
Vérifier qu'une valeur est un enregistrement de coffre valide.
isStoredVaultRecord: (value: unknown) => value is StoredVaultRecord
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | La valeur à vérifier. |
Définir la date du dernier déverrouillage d'un coffre.
markVaultRecordUsed: (input: { vaults: StoredVaultRecord[]; credentialId: string; usedAt?: string;}) => StoredVaultRecord[]
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { vaults: StoredVaultRecord[]; credentialId: string; usedAt?: string; } | Les enregistrements de coffres, l'identifiant de la passkey et la date, maintenant par défaut. |
Lire un registre de coffres, en écartant les enregistrements invalides.
parseVaultRegistry: (value: unknown) => VaultRegistry
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | Le registre, analysé depuis le JSON. |
Retirer un compte de chaque coffre, ainsi que les coffres laissés sans compte.
Cela ne retire que des enregistrements locaux. Sans coffre restant ni phrase de récupération exportée, le compte ne peut plus être déverrouillé.
removeAccountFromVaultRecords: (input: { vaults: StoredVaultRecord[]; address: `0x${string}`;}) => StoredVaultRecord[]
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { vaults: StoredVaultRecord[]; address: `0x${string}`; } | Les enregistrements de coffres et l'adresse du compte. |
Retirer l'enregistrement de coffre d'une passkey.
removeVaultRecord: (input: { vaults: StoredVaultRecord[]; credentialId: string;}) => StoredVaultRecord[]
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { vaults: StoredVaultRecord[]; credentialId: string; } | Les enregistrements de coffres et l'identifiant de la passkey. |
Retirer les enregistrements de coffres de plusieurs passkeys.
removeVaultRecords: (input: { vaults: StoredVaultRecord[]; credentialIds: Set<string>;}) => StoredVaultRecord[]
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { vaults: StoredVaultRecord[]; credentialIds: Set<string>; } | Les enregistrements de coffres et les identifiants des passkeys. |
Sérialiser des enregistrements de coffres sous forme de registre en JSON.
serializeVaultRegistry: (vaults: StoredVaultRecord[], space?: number) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
vaults | StoredVaultRecord[] | Les enregistrements de coffres. |
space | number | Indentation du JSON. |
Ajouter un enregistrement de coffre, ou remplacer celui de la même passkey, et le placer en premier.
upsertVaultRecord: (input: { vaults: StoredVaultRecord[]; record: StoredVaultRecord;}) => StoredVaultRecord[]
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { vaults: StoredVaultRecord[]; record: StoredVaultRecord; } | Les enregistrements de coffres et l'enregistrement à ajouter. |
Vérifier si un coffre contient un compte, sans tenir compte de la casse de l'adresse.
vaultHasAccount: (vault: StoredVaultRecord, address: string) => boolean
Paramètres
| Nom | Type | Description |
|---|---|---|
vault | StoredVaultRecord | L'enregistrement de coffre. |
address | string | L'adresse du compte. |
Enregistrements de coffres contenant les mêmes comptes, généralement les passkeys d'un même portefeuille.
export type VaultRegistryGroup = { id: string; accounts: StoredVaultAccount[]; passkeys: StoredVaultRecord[]; createdAt: string;};
Un compte avec les passkeys capables de le déverrouiller.
export type WalletGroup = { address: `0x${string}`; name: string; addressIndex: number; derivationPath: string; passkeys: StoredVaultRecord[];};
Raccourcir une adresse pour l'affichage, sous la forme 0x1234...abcd.
formatAddress: (address: string) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
address | string | L'adresse. |
Raccourcir pour l'affichage un identifiant de passkey de plus de 18 caractères.
formatCredentialId: (credentialId: string) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
credentialId | string | L'identifiant de la passkey. |
Obtenir l'index d'adresse du prochain compte à dériver : un de plus que le plus grand index des enregistrements, ou 0.
getNextAddressIndex: (records: StoredVaultRecord[]) => number
Paramètres
| Nom | Type | Description |
|---|---|---|
records | StoredVaultRecord[] | Les enregistrements de coffres. |
Trouver un compte d'un enregistrement de coffre, sans tenir compte de la casse de l'adresse.
getVaultAccount: (vault: StoredVaultRecord, address: string) => StoredVaultAccount | null
Paramètres
| Nom | Type | Description |
|---|---|---|
vault | StoredVaultRecord | L'enregistrement de coffre. |
address | string | L'adresse du compte. |
Retourne
| Type | Description |
|---|---|
StoredVaultAccount | null | Le compte, ou null. |
Identifier l'ensemble des comptes d'un enregistrement de coffre, par index d'adresse et adresse.
getVaultRegistryGroupId: (vault: StoredVaultRecord) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
vault | StoredVaultRecord | L'enregistrement de coffre. |
Regrouper les enregistrements de coffres contenant les mêmes comptes, du plus ancien au plus récent.
groupVaultRecordsBySeed: (vaults: StoredVaultRecord[]) => VaultRegistryGroup[]
Paramètres
| Nom | Type | Description |
|---|---|---|
vaults | StoredVaultRecord[] | Les enregistrements de coffres. |
Regrouper les enregistrements de coffres par compte, triés par index d'adresse.
groupVaultsByWallet: (vaults: StoredVaultRecord[]) => WalletGroup[]
Paramètres
| Nom | Type | Description |
|---|---|---|
vaults | StoredVaultRecord[] | Les enregistrements de coffres. |
Fusionner des enregistrements de coffres importés dans les enregistrements locaux, du plus récent au plus ancien.
Un enregistrement importé remplace l'enregistrement local de la même passkey.
mergeVaults: (localVaults: StoredVaultRecord[], importedVaults: StoredVaultRecord[]) => StoredVaultRecord[]
Paramètres
| Nom | Type | Description |
|---|---|---|
localVaults | StoredVaultRecord[] | Les enregistrements locaux. |
importedVaults | StoredVaultRecord[] | Les enregistrements importés. |
Les enregistrements de coffres peuvent être sauvegardés sur un serveur. Chaque sauvegarde n'expose que son enveloppe de coffre et l'identifiant de sa passkey : le reste de l'enregistrement est chiffré avec une clé dérivée de la phrase de récupération, si bien que le serveur n'apprend rien au-delà de l'adresse du portefeuille, et que n'importe quelle passkey du portefeuille peut restaurer toutes les sauvegardes.
Les sauvegardes d'un portefeuille, telles qu'exportées ou restaurées.
export type RemoteVaultBackupPackage = { version: 1; address: `0x${string}`; backups: RemoteVaultBackupRecord[]; exportedAt: string;};
Un enregistrement de coffre chiffré pour être sauvegardé sur un serveur.
Une sauvegarde expose son enveloppe de coffre, que seule sa propre passkey peut déchiffrer, avec l'identifiant de cette passkey. Le reste de l'enregistrement de coffre (adresses des comptes, noms, appareils) est chiffré avec une clé dérivée de la phrase de récupération, si bien que n'importe quelle passkey du portefeuille peut restaurer toutes les sauvegardes, tandis que le serveur n'apprend rien au-delà de l'adresse du portefeuille.
export type RemoteVaultBackupRecord = { version: 2; backupId: string; credentialId: string; envelope: PasskeyVaultEnvelopeData; salt: string; iv: string; ciphertext: string; createdAt: string;};
Envelopper les sauvegardes d'un portefeuille dans un paquet.
createRemoteVaultBackupPackage: (input: { address: `0x${string}`; backups: RemoteVaultBackupRecord[];}) => RemoteVaultBackupPackage
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: `0x${string}`; backups: RemoteVaultBackupRecord[]; } | L'adresse du portefeuille et ses sauvegardes. |
Chiffrer un enregistrement de coffre pour le sauvegarder.
La clé de sauvegarde est dérivée par HKDF d'un hash SHA-256 de la phrase de récupération, d'un sel aléatoire et de l'adresse. La phrase de récupération elle-même ne fait jamais partie de la sauvegarde.
createRemoteVaultBackupRecord: (input: { address: `0x${string}`; record: StoredVaultRecord; recoveryPhrase: string;}) => Promise<RemoteVaultBackupRecord>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: `0x${string}`; record: StoredVaultRecord; recoveryPhrase: string; } | L'adresse du portefeuille, l'enregistrement de coffre et la phrase de récupération du portefeuille. |
Hacher des sauvegardes avec SHA-256, sur une sérialisation JSON aux clés triées.
createVaultBackupDigest: (backups: RemoteVaultBackupRecord[]) => Promise<string>
Paramètres
| Nom | Type | Description |
|---|---|---|
backups | RemoteVaultBackupRecord[] | Les sauvegardes. |
Retourne
| Type | Description |
|---|---|
Promise<string> | L'empreinte, en hexadécimal. |
Construire le message que le portefeuille signe pour autoriser le stockage des sauvegardes.
createVaultBackupSignatureMessage: (input: { address: `0x${string}`; vaultCount: number; digest: string;}) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: `0x${string}`; vaultCount: number; digest: string; } | L'adresse du portefeuille, le nombre de sauvegardes et leur empreinte issue de createVaultBackupDigest(). |
Déchiffrer un enregistrement de coffre à partir d'une sauvegarde.
Le résultat n'est pas validé : vérifiez-le avec isStoredVaultRecord() avant de l'utiliser.
decryptRemoteVaultBackupRecord: (input: { address: `0x${string}`; backup: RemoteVaultBackupRecord; recoveryPhrase: string;}) => Promise<StoredVaultRecord>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: `0x${string}`; backup: RemoteVaultBackupRecord; recoveryPhrase: string; } | L'adresse du portefeuille, la sauvegarde et la phrase de récupération du portefeuille. |
Vérifier une adresse saisie par un utilisateur pour restaurer des sauvegardes, et lui appliquer la casse de contrôle.
normalizeBackupAddress: (value: string) => `0x${string}`
Paramètres
| Nom | Type | Description |
|---|---|---|
value | string | L'adresse. |
Lire un paquet de sauvegardes.
parseRemoteVaultBackupPackage: (value: unknown) => RemoteVaultBackupPackage
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | Le paquet, analysé depuis le JSON. |
Chaque portefeuille a une paire de clés ECDH P-256, stockée dans ses coffres, pour chiffrer des fichiers et des textes que lui seul peut déchiffrer. Sa clé publique peut être partagée avec une application dans une ressource Sign-In with Ethereum. Les textes chiffrés pour une application sont liés à l'origine de cette application, si bien qu'une autre application ne peut pas les faire déchiffrer.
Un fichier déchiffré.
export type WalletDecryptedFile = { name: string; type: string; bytes: Uint8Array; lastModified?: number;};
Un fichier chiffré pour le portefeuille qui l'a chiffré.
export type WalletEncryptedFilePackage = { version: 1; kind: 'organigram:wallet-encrypted-file'; algorithm: 'ECDH-P256+A256GCM'; recipient: { address: `0x${string}`; publicKey: JsonWebKey; keyVersion: number; }; file: { name: string; type: string; size: number; lastModified?: number; }; iv: string; ciphertext: string; encryptedAt: string;};
Un texte chiffré par un portefeuille pour lui-même, qu'une seule origine d'application peut faire déchiffrer.
export type WalletEncryptedPayload = { version: 1; kind: 'organigram:wallet-encrypted-payload'; algorithm: 'ECDH-P256+A256GCM'; appOrigin: string; recipient: { address: `0x${string}`; publicKey: JsonWebKey; keyVersion: number; }; iv: string; ciphertext: string; encryptedAt: string;};
La paire de clés ECDH P-256 d'un portefeuille pour le chiffrement de bout en bout, stockée dans ses coffres à passkeys.
Contient la clé privée en clair : ne la gardez que dans le coffre chiffré et en mémoire, et ne la stockez, ne l'envoyez ni ne la journalisez jamais ailleurs.
export type WalletEncryptionKeyPairPayload = { version: 1; algorithm: 'ECDH-P256'; privateKey: JsonWebKey; publicKey: JsonWebKey; keyVersion: number;};
La clé publique d'un portefeuille, lue dans une ressource Sign-In with Ethereum.
export type WalletEncryptionPublicKeySiweResource = { kind: typeof encryptionPublicKeyResourceKind; address: string; publicKey: JsonWebKey; keyVersion: number;};
Générer une nouvelle paire de clés ECDH P-256 pour un portefeuille.
La clé privée est exportable, afin de pouvoir être stockée dans les coffres à passkeys du portefeuille. Gardez-la là.
createWalletEncryptionKeyPair: () => Promise<WalletEncryptionKeyPairPayload>
Encoder la clé publique d'un portefeuille comme ressource d'un message Sign-In with Ethereum.
Se connecter avec cette ressource permet à l'application d'apprendre la clé publique du portefeuille, liée à son adresse par la signature.
createWalletEncryptionPublicKeySiweResource: (input: { address: `0x${string}`; keyPair: WalletEncryptionKeyPairPayload;}) => string
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: `0x${string}`; keyPair: WalletEncryptionKeyPairPayload; } | L'adresse du portefeuille et sa paire de clés. Seule la clé publique est encodée. |
Déchiffrer un fichier chiffré avec encryptFileWithWalletEncryptionKey().
decryptFileWithWalletEncryptionKey: (input: { encryptedPackage: WalletEncryptedFilePackage; keyPair: WalletEncryptionKeyPairPayload;}) => Promise<WalletDecryptedFile>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { encryptedPackage: WalletEncryptedFilePackage; keyPair: WalletEncryptionKeyPairPayload; } | Le paquet chiffré et la paire de clés du portefeuille. |
Déchiffrer un texte chiffré avec encryptPayloadWithWalletEncryptionKey().
decryptPayloadWithWalletEncryptionKey: (input: { encryptedPayload: WalletEncryptedPayload; appOrigin: string; keyPair: WalletEncryptionKeyPairPayload;}) => Promise<string>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { encryptedPayload: WalletEncryptedPayload; appOrigin: string; keyPair: WalletEncryptionKeyPairPayload; } | Le contenu chiffré, l'origine de l'application qui le demande, et la paire de clés du portefeuille. |
Chiffrer un fichier afin que seul le portefeuille détenant la paire de clés puisse le déchiffrer.
La clé AES-GCM est dérivée par ECDH entre les clés privée et publique de la même paire. Le nom, le type, la taille et la date du fichier restent en clair et ne sont pas authentifiés avec le texte chiffré.
encryptFileWithWalletEncryptionKey: (input: { address: `0x${string}`; file: File; keyPair: WalletEncryptionKeyPairPayload;}) => Promise<WalletEncryptedFilePackage>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: `0x${string}`; file: File; keyPair: WalletEncryptionKeyPairPayload; } | L'adresse du portefeuille, le fichier et la paire de clés. |
Chiffrer un texte afin que seul le portefeuille détenant la paire de clés puisse le déchiffrer, pour une origine d'application donnée.
L'origine de l'application, l'adresse et la version de clé sont authentifiées avec le texte chiffré, si bien que le contenu ne peut pas être déchiffré pour une autre application ni réétiqueté pour elle.
encryptPayloadWithWalletEncryptionKey: (input: { address: `0x${string}`; appOrigin: string; plaintext: string; keyPair: WalletEncryptionKeyPairPayload;}) => Promise<WalletEncryptedPayload>
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: `0x${string}`; appOrigin: string; plaintext: string; keyPair: WalletEncryptionKeyPairPayload; } | L'adresse du portefeuille, l'origine de l'application, le texte et la paire de clés. |
Lire un paquet de fichier chiffré.
parseWalletEncryptedFilePackage: (value: unknown) => WalletEncryptedFilePackage
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | Le paquet, analysé depuis le JSON. |
Lire un contenu chiffré.
parseWalletEncryptedPayload: (value: unknown) => WalletEncryptedPayload
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | Le contenu, analysé depuis le JSON. |
Lire une paire de clés de chiffrement de portefeuille.
parseWalletEncryptionKeyPair: (value: unknown) => WalletEncryptionKeyPairPayload
Paramètres
| Nom | Type | Description |
|---|---|---|
value | unknown | La paire de clés, analysée depuis le JSON. |
Lire la clé publique d'un portefeuille dans les ressources d'un message Sign-In with Ethereum.
Ne vous fiez au résultat qu'une fois la signature du message vérifiée.
parseWalletEncryptionPublicKeySiweResource: (input: { address: string; resources: string[] | undefined;}) => WalletEncryptionPublicKeySiweResource | null
Paramètres
| Nom | Type | Description |
|---|---|---|
input | { address: string; resources: string[] | undefined; } | L'adresse qui a signé le message, et les ressources du message. |
Retourne
| Type | Description |
|---|---|
WalletEncryptionPublicKeySiweResource | null | La clé publique, ou null si aucune ressource valide de cette adresse n'est trouvée. |
Modifier cette page
Sur cette page:
© 2026 Organigram SAS
Tous droits réservés.