はじめに
Seamsのしきい値ウォレットを使う場合は、まずウォレットを作成し、取引に署名します。その後で、復元、デバイス連携、権限の委任を追加してください。 Reactアプリと、ウォレットオリジン、リレーヤーURL、管理登録用の認証情報を設定したSeamsプロジェクトが必要です。 ウォレットオリジンは、ウォレットの保護されたUIとSDKアセットを配信する専用のオリジンです。
ウォレットの利用方法を選ぶ
以下の手順は、Seamsのしきい値ウォレットを作成するためのものです。 Meteor、HOT Wallet、Intear Walletを接続する場合は、外部NEARコネクターを参照してください。 外部接続にはSeamsのプロバイダーやログインは不要です。 この機能は開発プレビューです。
Google SSOを使うアプリは、同じログインでウォレット設定を開けます。 SDK 0.42.0では、関連付けたウォレットに対してGoogle IDトークンとバックエンド経由の引き渡しを使えます。 署名とセキュリティ設定の変更には、引き続き所有者の認証が必要です。
1. SDKをインストール {#_1-install-the-sdk}
pnpm add @seams/wallet@0.42.02. プロバイダーを配置
アプリのルート付近で、分離されたウォレットオリジンを一度設定します。 seamsTestnetConfigには、ウォレットオリジン、リレーヤーURL、管理登録用の認証情報が必要です。 その他の設定にはSDKの既定値を使います。この例ではimport.meta.envから値を読み込みます。 同じ環境変数名を使うか、独自の設定ローダーを使用してください。 別のネットワークを設定する場合はchainsを渡します。テストネット以外ではdefineSeamsConfigを使います。
このドキュメントは@seams/wallet 0.42.0を対象としています。 ウォレットオリジンのアセットと@seams/wallet-serverも、対応するリリースに合わせてください。 既存の実装を更新する前に、デプロイ要件を確認してください。
VoiceIDは、音声の登録、アンロック、送金承認に使う任意のパッケージです。 エンジンとモデルは、VoiceIDを使うときだけ読み込みます。
ウォレットiframeのプロトコルは23.0.0、復元CLIは0.29.0です。 導入とデプロイの要件はリリース 0.42.0を参照してください。
import { SeamsWebProvider, seamsTestnetConfig, useSeams } from '@seams/wallet/react';
// Everything else — wallet service path, SDK base path, relayer account, chain
// RPC and explorer URLs — comes from the SDK defaults.
const seamsConfig = seamsTestnetConfig({
walletOrigin: import.meta.env.VITE_WALLET_ORIGIN,
relayerUrl: import.meta.env.VITE_RELAYER_URL,
publishableKey: import.meta.env.VITE_SEAMS_PUBLISHABLE_KEY,
});
function WalletApp() {
const { loginState } = useSeams();
return <p>{loginState.isLoggedIn ? 'Wallet unlocked' : 'Wallet locked'}</p>;
}
export function App() {
return (
<SeamsWebProvider config={seamsConfig}>
<WalletApp />
</SeamsWebProvider>
);
}ウォレットUIはSeamsWebProviderの内側に配置します。 ウォレットサービスとSDKアセットは、設定したウォレットオリジンから配信してください。
登録UI全体を利用する場合は、ホスト型メニューの実装例にある HostedRegistrationを使います。メニューは登録画面を開いている間にセットアップを準備します。 以下のカスタムボタンは、登録処理の呼び出し内でセットアップを開始します。
3. ウォレットを作成
プロバイダーの内側に、登録の実装例にあるボタンを配置します。 ユーザーがクリックすると、SDKがパスキーの認証画面を開きます。 この例では、その登録処理の進行状況と結果をログに出力します。
import type { RegistrationFlowEvent, SeamsWeb } from '@seams/wallet';
import { useSeams, type SeamsContextType } from '@seams/wallet/react';
function logRegistrationEvent(event: RegistrationFlowEvent): void {
console.log(event.phase, event.status, event.message);
}
function assertNever(value: never): never {
throw new Error(`Unexpected NEAR readiness result: ${JSON.stringify(value)}`);
}
async function createWallet(
registerWallet: SeamsContextType['registerWallet'],
seams: SeamsWeb,
registration: Parameters<SeamsContextType['registerWallet']>[0],
): Promise<void> {
try {
const result = await registerWallet({
...registration,
options: { ...registration.options, onEvent: logRegistrationEvent },
});
if (!result.success) {
console.error('Registration failed:', result.error);
return;
}
// `walletId` is the stable identifier for every later wallet operation.
console.log(`Wallet ${result.walletId} registered (${result.kind})`);
if (
result.kind === 'ecdsa_wallet_registered_near_pending' ||
result.kind === 'near_wallet_registered_pending'
) {
const near = await seams.registration.waitForNearAccount({ walletId: result.walletId });
switch (near.kind) {
case 'near_ready':
console.log('NEAR account ready:', near.nearAccountId);
break;
case 'near_failed_retryable':
console.warn('NEAR provisioning needs a retry:', near.reason);
break;
case 'timed_out':
console.warn('NEAR is still pending. Keep this wallet id and check readiness again.');
break;
default:
assertNever(near);
}
}
} catch (error) {
console.error('Wallet creation interrupted:', error);
}
}
export function CreateWalletButton({ registration }: {
registration: Parameters<SeamsContextType['registerWallet']>[0];
}) {
const { registerWallet, seams } = useSeams();
return (
<button onClick={createWallet.bind(null, registerWallet, seams, registration)}>
Create wallet
</button>
);
}結果の各分岐と再試行の扱いは、ウォレットを作成を参照してください。
4. 取引に署名
要求した署名者の準備が完了すると、useSeams().walletからログイン中のウォレットの署名メソッドを利用できます。 これらのメソッドには取引だけを渡します。各要求でウォレットの確認画面が開き、ユーザーがウォレットの認証方法で取引を承認します。
ログイン中とは別のウォレットを指定する場合は、useSeams().seamsを使い、呼び出しに明示的なwalletSessionを渡します。
アクションはfunctionCallやtransferなどのヘルパーで作成してください。 { type: ActionType.FunctionCall, … }のようなオブジェクトを直接組み立てないでください。 onEventにlogWalletEvents()を渡すと、コンソールに進行状況を出力できます。
transferには単位付きの金額を渡します。transfer('1 NEAR')は1 NEAR、 transfer('1000 yoctoNEAR')は1000 yoctoNEARを送金します。単位のない文字列はコンパイルできません。 実行時に計算した金額には、NEARの小数文字列を受け取るparseNear(amount)、 またはyoctoNEAR単位の値を受け取るyoctoNear(amount)を使います。
EVMのvalueはwei単位のbigintです。parseEther('0.5')で記述できます。 このヘルパーは、チェーンの小数点以下18桁のネイティブ通貨(ETH、POLなど)の金額を受け取ります。 小数桁数が異なるERC-20などのトークンには、parseUnits('1.5', 6)を使います。 これらのヘルパーは、負数、数値ではない値、許容桁数を超える値に対してAmountErrorを送出します。
seams.evmとseams.tempoは、どちらもsignTransaction、signAndSendTransaction、advancedを提供します。 取引形式は異なり、EVMはEIP-1559、TempoはEIP-2718を使います。
これらの要求に事前のアンロック操作は不要です。 取引ごとの認証画面を省いて繰り返し署名する場合は、署名セッションを作成します。 ウォレットセッションと署名レーンを参照してください。
高度な機能を追加
最初の署名処理が動作したら、デバイス連携、鍵のエクスポート、復元に進んでください。 認証方法、ポリシー、デプロイ時の境界についてはガイドを参照してください。