import * as ed from '@noble/ed25519';
import { Hex } from 'viem';
import { mnemonicToAccount } from 'viem/accounts';
import axios from 'axios';
import * as qrcode from 'qrcode-terminal';
/*** EIP-712 helper code ***/
const SIGNED_KEY_REQUEST_VALIDATOR_EIP_712_DOMAIN = {
name: 'Farcaster SignedKeyRequestValidator',
version: '1',
chainId: 10,
verifyingContract: '0x00000000fc700472606ed4fa22623acf62c60553',
} as const;
const SIGNED_KEY_REQUEST_TYPE = [
{ name: 'requestFid', type: 'uint256' },
{ name: 'key', type: 'bytes' },
{ name: 'deadline', type: 'uint256' },
] as const;
(async () => {
/*** Generating a keypair ***/
const privateKey = ed.utils.randomPrivateKey();
const publicKeyBytes = await ed.getPublicKey(privateKey);
const key = '0x' + Buffer.from(publicKeyBytes).toString('hex');
/*** Generating a Signed Key Request signature ***/
const appFid = process.env.APP_FID;
const account = mnemonicToAccount(process.env.APP_MNEMONIC);
const deadline = Math.floor(Date.now() / 1000) + 86400; // signature is valid for 1 day
const signature = await account.signTypedData({
domain: SIGNED_KEY_REQUEST_VALIDATOR_EIP_712_DOMAIN,
types: {
SignedKeyRequest: SIGNED_KEY_REQUEST_TYPE,
},
primaryType: 'SignedKeyRequest',
message: {
requestFid: BigInt(appFid),
key,
deadline: BigInt(deadline),
},
});
/*** Creating a Signed Key Request ***/
const farcasterClientApi = 'https://api.farcaster.xyz';
const { token, deeplinkUrl } = await axios
.post(`${farcasterClientApi}/v2/signed-key-requests`, {
key,
requestFid: appFid,
signature,
deadline,
})
.then((response) => response.data.result.signedKeyRequest);
qrcode.generate(deeplinkUrl, console.log);
console.log('scan this with your phone');
console.log('deep link:', deeplinkUrl);
const poll = async (token: string) => {
while (true) {
// sleep 1s
await new Promise((r) => setTimeout(r, 2000));
console.log('polling signed key request');
const signedKeyRequest = await axios
.get(`${farcasterClientApi}/v2/signed-key-request`, {
params: {
token,
},
})
.then((response) => response.data.result.signedKeyRequest);
if (signedKeyRequest.state === 'completed') {
console.log('Signed Key Request completed:', signedKeyRequest);
/**
* At this point the signer has been registered onchain and you can start submitting
* messages to hubs signed by its key:
* ```
* const signer = Ed25519Signer.fromPrivateKey(privateKey)._unsafeUnwrap();
* const message = makeCastAdd(..., signer)
* ```
*/
break;
}
}
};
await poll(token);
})();