本文へ移動

はじめに

Seamsをインストールし、ウォレットの作成と最初の取引への署名を行います。

はじめに ​

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} ​

sh
pnpm add @seams/wallet@0.42.0

2. プロバイダーを配置 ​

アプリのルート付近で、分離されたウォレットオリジンを一度設定します。 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を参照してください。

tsx
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がパスキーの認証画面を開きます。 この例では、その登録処理の進行状況と結果をログに出力します。

tsx
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を使います。

これらの要求に事前のアンロック操作は不要です。 取引ごとの認証画面を省いて繰り返し署名する場合は、署名セッションを作成します。 ウォレットセッションと署名レーンを参照してください。

高度な機能を追加 ​

最初の署名処理が動作したら、デバイス連携、鍵のエクスポート、復元に進んでください。 認証方法、ポリシー、デプロイ時の境界についてはガイドを参照してください。