{"version":3,"file":"resolveSns.cjs","sources":["../../../src/domain/resolveSns.ts"],"sourcesContent":["import {\r\n  Address,\r\n  fetchEncodedAccount,\r\n  fetchEncodedAccounts,\r\n  getPublicKeyFromAddress,\r\n} from \"@solana/kit\";\r\n\r\nimport { addressCodec, utf8Codec } from \"../codecs\";\r\nimport {\r\n  CouldNotFindNftOwnerError,\r\n  DomainDoesNotExistError,\r\n  InvalidRoaError,\r\n  InvalidValidationError,\r\n  PdaOwnerNotAllowedError,\r\n  RecordMalformedError,\r\n} from \"../errors\";\r\nimport { getSnsNftOwner } from \"../nft/getSnsNftOwner\";\r\nimport { getRecordV1Address } from \"../record/getRecordV1Address\";\r\nimport { getRecordV2Address } from \"../record/getRecordV2Address\";\r\nimport { NftState, NftTag } from \"../states/nft\";\r\nimport { RecordState } from \"../states/record\";\r\nimport { RegistryState } from \"../states/registry\";\r\nimport { Record } from \"../types/record\";\r\nimport { Validation } from \"../types/validation\";\r\nimport { checkAddressOnCurve } from \"../utils/checkAddressOnCurve\";\r\nimport { uint8ArrayToHex } from \"../utils/uint8Array/uint8ArrayToHex\";\r\nimport { uint8ArraysEqual } from \"../utils/uint8Array/uint8ArraysEqual\";\r\nimport { getSnsDomainAddress } from \"./getSnsDomainAddress\";\r\nimport { ResolveSnsParams } from \"./resolveTypes\";\r\n\r\nconst verifySolRecordV1Signature = async ({\r\n  data,\r\n  signature,\r\n  address,\r\n}: {\r\n  data: Uint8Array;\r\n  signature: Uint8Array<ArrayBuffer>;\r\n  address: Address;\r\n}) => {\r\n  const publicKey = await getPublicKeyFromAddress(address);\r\n  const encodedHexString = utf8Codec.encode(uint8ArrayToHex(data));\r\n\r\n  return crypto.subtle.verify(\r\n    { name: \"Ed25519\" },\r\n    publicKey,\r\n    signature,\r\n    encodedHexString\r\n  );\r\n};\r\n\r\n/** Resolves a TLD-trimmed SNS name using SNS-IP 5 behavior. */\r\nexport const resolveSns = async ({\r\n  rpc,\r\n  domain,\r\n  options,\r\n}: ResolveSnsParams): Promise<Address> => {\r\n  const { domainAddress } = await getSnsDomainAddress({ domain });\r\n  const nftAddress = await NftState.getAddress(domainAddress);\r\n  const solRecordV1Address = await getRecordV1Address({\r\n    domain,\r\n    record: Record.SOL,\r\n  });\r\n  const solRecordV2Address = await getRecordV2Address({\r\n    domain,\r\n    record: Record.SOL,\r\n  });\r\n  const [domainAccount, nftAccount, solRecordV1Account, solRecordV2Account] =\r\n    await fetchEncodedAccounts(rpc, [\r\n      domainAddress,\r\n      nftAddress,\r\n      solRecordV1Address,\r\n      solRecordV2Address,\r\n    ]);\r\n\r\n  if (!domainAccount.exists) {\r\n    throw new DomainDoesNotExistError(`Domain ${domain} does not exist`);\r\n  }\r\n\r\n  const registry = RegistryState.deserialize(domainAccount.data);\r\n\r\n  if (nftAccount.exists) {\r\n    const nftRecord = NftState.deserialize(nftAccount.data);\r\n    if (nftRecord.tag === NftTag.ActiveRecord) {\r\n      const nftOwner = await getSnsNftOwner({ rpc, domainAddress });\r\n      if (!nftOwner) {\r\n        throw new CouldNotFindNftOwnerError();\r\n      }\r\n      return nftOwner;\r\n    }\r\n  }\r\n\r\n  recordV2: if (solRecordV2Account.exists) {\r\n    const recordV2 = RecordState.deserialize(solRecordV2Account.data);\r\n    const stalenessId = recordV2.getStalenessId();\r\n    const roaId = recordV2.getRoAId();\r\n    const content = recordV2.getContent();\r\n\r\n    if (content.length !== 32) {\r\n      throw new RecordMalformedError(\"Record is malformed\");\r\n    }\r\n\r\n    if (\r\n      recordV2.header.rightOfAssociationValidation !== Validation.Solana ||\r\n      recordV2.header.stalenessValidation !== Validation.Solana\r\n    ) {\r\n      throw new InvalidValidationError();\r\n    }\r\n\r\n    if (registry.owner !== addressCodec.decode(stalenessId)) {\r\n      break recordV2;\r\n    }\r\n\r\n    if (uint8ArraysEqual(roaId, content)) {\r\n      return addressCodec.decode(content);\r\n    }\r\n\r\n    throw new InvalidRoaError(\r\n      `The RoA ID should be ${addressCodec.decode(content)} but is ${addressCodec.decode(roaId)} `\r\n    );\r\n  }\r\n\r\n  if (solRecordV1Account.exists) {\r\n    const data = new Uint8Array([\r\n      ...solRecordV1Account.data.slice(\r\n        RegistryState.HEADER_LEN,\r\n        RegistryState.HEADER_LEN + 32\r\n      ),\r\n      ...addressCodec.encode(solRecordV1Address),\r\n    ]);\r\n    const signature = solRecordV1Account.data.slice(\r\n      RegistryState.HEADER_LEN + 32,\r\n      RegistryState.HEADER_LEN + 32 + 64\r\n    );\r\n    const valid = await verifySolRecordV1Signature({\r\n      data,\r\n      signature,\r\n      address: registry.owner,\r\n    });\r\n\r\n    if (valid) {\r\n      return addressCodec.decode(\r\n        solRecordV1Account.data.slice(\r\n          RegistryState.HEADER_LEN,\r\n          RegistryState.HEADER_LEN + 32\r\n        )\r\n      );\r\n    }\r\n  }\r\n\r\n  if (!checkAddressOnCurve(registry.owner)) {\r\n    if (options.allowPda === \"any\") {\r\n      return registry.owner;\r\n    }\r\n\r\n    if (options.allowPda) {\r\n      const ownerAccount = await fetchEncodedAccount(rpc, registry.owner);\r\n\r\n      if (!ownerAccount.exists) {\r\n        throw new PdaOwnerNotAllowedError(\"Invalid domain owner account\");\r\n      }\r\n\r\n      if (\r\n        options.programIds.some(\r\n          (programId) => ownerAccount.programAddress === programId\r\n        )\r\n      ) {\r\n        return registry.owner;\r\n      }\r\n\r\n      throw new PdaOwnerNotAllowedError(\r\n        `The program ${ownerAccount.programAddress} is not allowed`\r\n      );\r\n    }\r\n\r\n    throw new PdaOwnerNotAllowedError();\r\n  }\r\n\r\n  return registry.owner;\r\n};\r\n"],"names":["getPublicKeyFromAddress","utf8Codec","uint8ArrayToHex","getSnsDomainAddress","NftState","getRecordV1Address","Record","getRecordV2Address","fetchEncodedAccounts","DomainDoesNotExistError","registry","RegistryState","NftTag","getSnsNftOwner","CouldNotFindNftOwnerError","RecordState","RecordMalformedError","Validation","InvalidValidationError","addressCodec","uint8ArraysEqual","InvalidRoaError","checkAddressOnCurve","fetchEncodedAccount","PdaOwnerNotAllowedError"],"mappings":";;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,0BAA0B,GAAG,OAAO,EACxC,IAAI,EACJ,SAAS,EACT,OAAO,GAKR,KAAI;AACH,IAAA,MAAM,SAAS,GAAG,MAAMA,2BAAuB,CAAC,OAAO,CAAC;IACxD,MAAM,gBAAgB,GAAGC,gBAAS,CAAC,MAAM,CAACC,+BAAe,CAAC,IAAI,CAAC,CAAC;AAEhE,IAAA,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CACzB,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,SAAS,EACT,SAAS,EACT,gBAAgB,CACjB;AACH,CAAC;AAED;AACO,MAAM,UAAU,GAAG,OAAO,EAC/B,GAAG,EACH,MAAM,EACN,OAAO,GACU,KAAsB;IACvC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAMC,uCAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/D,MAAM,UAAU,GAAG,MAAMC,YAAQ,CAAC,UAAU,CAAC,aAAa,CAAC;AAC3D,IAAA,MAAM,kBAAkB,GAAG,MAAMC,qCAAkB,CAAC;QAClD,MAAM;QACN,MAAM,EAAEC,aAAM,CAAC,GAAG;AACnB,KAAA,CAAC;AACF,IAAA,MAAM,kBAAkB,GAAG,MAAMC,qCAAkB,CAAC;QAClD,MAAM;QACN,MAAM,EAAED,aAAM,CAAC,GAAG;AACnB,KAAA,CAAC;AACF,IAAA,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,kBAAkB,CAAC,GACvE,MAAME,wBAAoB,CAAC,GAAG,EAAE;QAC9B,aAAa;QACb,UAAU;QACV,kBAAkB;QAClB,kBAAkB;AACnB,KAAA,CAAC;AAEJ,IAAA,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;AACzB,QAAA,MAAM,IAAIC,8BAAuB,CAAC,UAAU,MAAM,CAAA,eAAA,CAAiB,CAAC;;IAGtE,MAAMC,UAAQ,GAAGC,sBAAa,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC;AAE9D,IAAA,IAAI,UAAU,CAAC,MAAM,EAAE;QACrB,MAAM,SAAS,GAAGP,YAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC;QACvD,IAAI,SAAS,CAAC,GAAG,KAAKQ,UAAM,CAAC,YAAY,EAAE;YACzC,MAAM,QAAQ,GAAG,MAAMC,6BAAc,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC;YAC7D,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,IAAIC,gCAAyB,EAAE;;AAEvC,YAAA,OAAO,QAAQ;;;AAInB,IAAA,QAAQ,EAAE,IAAI,kBAAkB,CAAC,MAAM,EAAE;QACvC,MAAM,QAAQ,GAAGC,oBAAW,CAAC,WAAW,CAAC,kBAAkB,CAAC,IAAI,CAAC;AACjE,QAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE;AAC7C,QAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE;AACjC,QAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,EAAE;AAErC,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE;AACzB,YAAA,MAAM,IAAIC,2BAAoB,CAAC,qBAAqB,CAAC;;QAGvD,IACE,QAAQ,CAAC,MAAM,CAAC,4BAA4B,KAAKC,qBAAU,CAAC,MAAM;YAClE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,KAAKA,qBAAU,CAAC,MAAM,EACzD;YACA,MAAM,IAAIC,6BAAsB,EAAE;;QAGpC,IAAIR,UAAQ,CAAC,KAAK,KAAKS,mBAAY,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE;AACvD,YAAA,MAAM,QAAQ;;AAGhB,QAAA,IAAIC,iCAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE;AACpC,YAAA,OAAOD,mBAAY,CAAC,MAAM,CAAC,OAAO,CAAC;;AAGrC,QAAA,MAAM,IAAIE,sBAAe,CACvB,wBAAwBF,mBAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAW,QAAA,EAAAA,mBAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA,CAAA,CAAG,CAC7F;;AAGH,IAAA,IAAI,kBAAkB,CAAC,MAAM,EAAE;AAC7B,QAAA,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC;AAC1B,YAAA,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAC9BR,sBAAa,CAAC,UAAU,EACxBA,sBAAa,CAAC,UAAU,GAAG,EAAE,CAC9B;AACD,YAAA,GAAGQ,mBAAY,CAAC,MAAM,CAAC,kBAAkB,CAAC;AAC3C,SAAA,CAAC;QACF,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAC7CR,sBAAa,CAAC,UAAU,GAAG,EAAE,EAC7BA,sBAAa,CAAC,UAAU,GAAG,EAAE,GAAG,EAAE,CACnC;AACD,QAAA,MAAM,KAAK,GAAG,MAAM,0BAA0B,CAAC;YAC7C,IAAI;YACJ,SAAS;YACT,OAAO,EAAED,UAAQ,CAAC,KAAK;AACxB,SAAA,CAAC;QAEF,IAAI,KAAK,EAAE;YACT,OAAOS,mBAAY,CAAC,MAAM,CACxB,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAC3BR,sBAAa,CAAC,UAAU,EACxBA,sBAAa,CAAC,UAAU,GAAG,EAAE,CAC9B,CACF;;;IAIL,IAAI,CAACW,yBAAmB,CAACZ,UAAQ,CAAC,KAAK,CAAC,EAAE;AACxC,QAAA,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE;YAC9B,OAAOA,UAAQ,CAAC,KAAK;;AAGvB,QAAA,IAAI,OAAO,CAAC,QAAQ,EAAE;YACpB,MAAM,YAAY,GAAG,MAAMa,uBAAmB,CAAC,GAAG,EAAEb,UAAQ,CAAC,KAAK,CAAC;AAEnE,YAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;AACxB,gBAAA,MAAM,IAAIc,8BAAuB,CAAC,8BAA8B,CAAC;;AAGnE,YAAA,IACE,OAAO,CAAC,UAAU,CAAC,IAAI,CACrB,CAAC,SAAS,KAAK,YAAY,CAAC,cAAc,KAAK,SAAS,CACzD,EACD;gBACA,OAAOd,UAAQ,CAAC,KAAK;;YAGvB,MAAM,IAAIc,8BAAuB,CAC/B,CAAA,YAAA,EAAe,YAAY,CAAC,cAAc,CAAiB,eAAA,CAAA,CAC5D;;QAGH,MAAM,IAAIA,8BAAuB,EAAE;;IAGrC,OAAOd,UAAQ,CAAC,KAAK;AACvB;;;;"}