Skip to content

密钥网关

密钥网关用于向密钥注册表添加新密钥。

如需为 Farcaster 账户添加新的公钥,请使用密钥网关。

读取操作

nonces

返回指定地址的下一个可用 nonce 值。用于在 addFor 操作中生成 EIP-712 签名。

参数类型描述
owneraddress需要查询 nonce 值的地址

写入操作

add

为调用者的 fid 添加新密钥,并将其状态设为 Added。如果密钥已注册则回滚操作。

参数类型描述
keyTypeuint32必须设为 1。这是当前唯一支持的 keyType 值。
keybytes待添加的公钥
metadataTypeuint8必须设为 1。这是当前唯一支持的 metadataType 值。
metadatabytes编码后的 SignedKeyRequestMetadata

addFor

通过提供签名代表其他 fid 添加密钥。所有者必须签署 EIP-712 Add 消息来批准该密钥。如果密钥已注册则回滚操作。

参数类型描述
fidOwneraddressfid 所有者的地址
keyTypeuint32必须设为 1。这是当前唯一支持的 keyType 值。
keybytes待添加的公钥
metadataTypeuint8必须设为 1。这是当前唯一支持的 metadataType 值。
metadatabytes编码后的 SignedKeyRequestMetadata
deadlineuint256签名过期时间戳
sigbytes来自 fidOwner 的 EIP-712 Add 签名

Add 签名

要代表其他账户添加密钥,必须提供符合以下格式的 EIP-712 类型签名:

Add(address owner,uint32 keyType,bytes key,uint8 metadataType,bytes metadata,uint256 nonce,uint256 deadline)

参数类型描述
owneraddress拥有 fid 的地址。该类型化消息必须由此地址签名。
keyTypeuint32必须设为 1。这是当前唯一支持的 keyType 值。
keybytes待添加的公钥
metadataTypeuint8必须设为 1。这是当前唯一支持的 metadataType 值。
metadatabytes编码后的 SignedKeyRequestMetadata
nonceuint256owner 地址的当前 nonce 值
deadlineuint256签名过期时间戳
ts
import { ViemWalletEip712Signer } from '@farcaster/hub-web';
import { walletClient, account } from './clients.ts';
import { getPublicKey } from './signer.ts';
import { readNonce, getDeadline } from './helpers.ts';

const publicKey = await getPublicKey();
const metadata = await getMetadata();
const nonce = await readNonce();
const deadline = getDeadline();

const eip712Signer = new ViemWalletEip712Signer(walletClient);
const signature = await eip712signer.signAdd({
  owner: account,
  keyType: 1,
  key: publicKey,
  metadataType: 1,
  metadata,
  nonce,
  deadline,
});
ts
import { KEY_GATEWAY_EIP_712_TYPES } from '@farcaster/hub-web';
import { bytesToHex } from 'viem';
import { walletClient, account } from './clients.ts';
import { getPublicKey } from './signer.ts';
import { getMetadata } from './metadata.ts';
import { readNonce, getDeadline } from './helpers.ts';

const publicKey = await getPublicKey();
const metadata = await getMetadata();
const nonce = await readNonce();
const deadline = getDeadline();

const signature = await walletClient.signTypedData({
  account,
  ...KEY_GATEWAY_EIP_712_TYPES,
  primaryType: 'Add',
  message: {
    owner: account,
    keyType: 1,
    key: bytesToHex(publicKey),
    metadataType: 1,
    metadata,
    nonce,
    deadline,
  },
});
ts
import { KEY_GATEWAY_ADDRESS, keyGatewayABI } from '@farcaster/hub-web';
import { publicClient, account } from './clients.ts';

export const getDeadline = () => {
  const now = Math.floor(Date.now() / 1000);
  const oneHour = 60 * 60;
  return now + oneHour;
};

export const readNonce = async () => {
  return await publicClient.readContract({
    address: KEY_GATEWAY_ADDRESS,
    abi: keyGatewayABI,
    functionName: 'nonces',
    args: [account],
  });
};
ts
import { ViemLocalEip712Signer } from '@farcaster/hub-web';
import { privateKeyToAccount } from 'viem/accounts';
import { getDeadline } from './helpers.ts';
import { getPublicKey } from './signer.ts';

// App account
export const appAccount = privateKeyToAccount('0x...');

const deadline = getDeadline();
const publicKey = await getPublicKey();

export const getMetadata = async () => {
  const eip712signer = new ViemLocalEip712Signer(appAccount);
  const metadata = await eip712signer.getSignedKeyRequestMetadata({
    requestFid: 9152n, // App fid
    key: publicKey,
    deadline,
  });
  if (metadata.isOk()) {
    return metadata.value;
  }
};
ts
import * as ed from '@noble/ed25519';
import { NobleEd25519Signer } from '@farcaster/hub-web';

const privateKeyBytes = ed.utils.randomPrivateKey();
export const accountKey = new NobleEd25519Signer(privateKeyBytes);

export const getPublicKey = async () => {
  const accountKeyResult = await accountKey.getSignerKey();
  if (accountKeyResult.isOk()) {
    return accountKeyResult.value;
  }
};
ts
import { createWalletClient, createPublicClient, custom, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { optimism } from 'viem/chains';

export const publicClient = createPublicClient({
  chain: optimism,
  transport: http(),
});

export const walletClient = createWalletClient({
  chain: optimism,
  transport: custom(window.ethereum),
});

// JSON-RPC Account
export const [account] = await walletClient.getAddresses();

// Local Account
export const account = privateKeyToAccount('0x...');

错误类型

错误类型选择器描述
InvalidMetadatabcecb64a提供的签名元数据无效。
InvalidSignature8baa579f提供的签名无效。可能是格式错误,或由错误的地址签署。
SignatureExpired0819bdcd提供的签名已过期。请向签署者获取带有更晚截止时间戳的新签名。

源代码

KeyGateway.sol