import { type Address, type Chain, type Hex, type PublicClient, type WalletClient, encodeAbiParameters, getAddress, keccak256, pad, stringToBytes, toHex, } from 'viem' import type { PrivateKeyAccount } from 'viem/accounts' import { MIN_GAS_PRICE, makeViemClients } from '../chain' import { waitForReceiptResilient } from '../identity/receipt' /** * SPACE ID on 0G mainnet uses the SANN architecture. Contracts discovered via * `RegistrarController.sann()` + `SANN.registry()` + `SANN.tldBase(IDENTIFIER)`. */ export const SANN_SUFFIX = '.anima.0g' as const export const SANN_ADDRESSES = { controller: '0xD7b837A0E388B4c25200983bdAa3EF3A83ca86b7' as Address, resolver: '0x6D3B3F99177FB2A5de7F9E928a9BD807bF7b5BAD' as Address, sann: '0x9af6F1244df403dAe39Eb2D0be1C3fD0B38e0789' as Address, registry: '0x5dC881dDA4e4a8d312be3544AD13118D1a04Cb17' as Address, tldBase0G: '0x75f7590Def0905566805298F021A7174715eF0cd' as Address, tldIdentifier: 449205675366457712613706471770511817162982777845754732038879201565074548n, } const REGISTRY_ABI = [ { type: 'function', name: 'owner', stateMutability: 'view', inputs: [{ name: 'node', type: 'bytes32' }], outputs: [{ type: 'address' }], }, { type: 'function', name: 'setResolver', stateMutability: 'nonpayable', inputs: [ { name: 'node', type: 'bytes32' }, { name: 'resolver', type: 'address' }, ], outputs: [], }, { type: 'function', name: 'setSubnodeOwner', stateMutability: 'nonpayable', inputs: [ { name: 'node', type: 'bytes32' }, { name: 'label', type: 'bytes32' }, { name: 'owner', type: 'address' }, ], outputs: [{ type: 'bytes32' }], }, ] as const const RESOLVER_ABI = [ { type: 'function', name: 'setText', stateMutability: 'nonpayable', inputs: [ { name: 'node', type: 'bytes32' }, { name: 'key', type: 'string' }, { name: 'value', type: 'string' }, ], outputs: [], }, { type: 'function', name: 'text', stateMutability: 'view', inputs: [ { name: 'node', type: 'bytes32' }, { name: 'key', type: 'string' }, ], outputs: [{ type: 'string' }], }, ] as const /** SANN-style namehash. Note: NOT the same as ENS namehash. */ export function sannNamehash(tldIdentifier: bigint, tld: string, sub: string[]): Hex { const idBytes = pad(toHex(tldIdentifier), { size: 32 }) const zero: Hex = `0x${'00'.repeat(32)}` const identifierNode = keccak256( encodeAbiParameters([{ type: 'bytes32' }, { type: 'bytes32' }], [zero, idBytes]), ) const tldHash = keccak256(stringToBytes(tld)) let node = keccak256( encodeAbiParameters([{ type: 'bytes32' }, { type: 'bytes32' }], [identifierNode, tldHash]), ) for (const label of sub) { const labelHash = keccak256(stringToBytes(label)) node = keccak256( encodeAbiParameters([{ type: 'bytes32' }, { type: 'bytes32' }], [node, labelHash]), ) } return node } /** Compute the SANN node for `