@@ -2,22 +2,23 @@ import { Platform } from "react-native";
22import { get as assert , create } from "react-native-passkeys" ;
33
44import { sdk } from "@farcaster/miniapp-sdk" ;
5+ import { bufferToBase64URLString } from "@simplewebauthn/browser" ;
56import { getConnection , signMessage } from "@wagmi/core" ;
67import { hc , parseResponse , type InferResponseType } from "hono/client" ;
78import { check , number , object , parse , pipe , safeParse , string , ValiError } from "valibot" ;
8- import { UserRejectedRequestError } from "viem" ;
99
10+ import { hashMessage , hexToBytes , UserRejectedRequestError } from "viem" ;
1011import AUTH_EXPIRY from "@exactly/common/AUTH_EXPIRY" ;
1112import deriveAddress from "@exactly/common/deriveAddress" ;
1213import domain from "@exactly/common/domain" ;
13- import { Credential } from "@exactly/common/validation" ;
1414
15+ import { Credential } from "@exactly/common/validation" ;
1516import { login as loginIntercom , logout as logoutIntercom } from "./intercom" ;
1617import { decrypt , decryptPIN , encryptPIN , session } from "./panda" ;
1718import queryClient , { APIError , triage , type AuthMethod } from "./queryClient" ;
1819import { classifyError } from "./reportError" ;
19- import ownerConfig from "./wagmi/owner" ;
2020
21+ import ownerConfig from "./wagmi/owner" ;
2122import type { ExaAPI } from "@exactly/server/api" ; // eslint-disable-line @nx/enforce-module-boundaries
2223
2324queryClient . setQueryDefaults < number | undefined > ( [ "auth" ] , {
@@ -158,6 +159,37 @@ export async function setCardPIN(pin: string) {
158159 if ( ! response . ok ) throw new APIError ( response . status , stringOrLegacy ( await response . json ( ) ) ) ;
159160}
160161
162+ export async function signCard ( ) {
163+ await auth ( ) ;
164+ const address = getConnection ( ownerConfig ) . address ;
165+ if ( ! address ) throw new Error ( "no owner wallet connected" ) ;
166+ const token = await api . card . $patch ( { json : { method : "siwe" , action : "challenge" } } ) ;
167+ if ( ! token . ok ) throw new APIError ( token . status , stringOrLegacy ( await token . json ( ) ) ) ;
168+ const { challenge } = parse ( object ( { challenge : string ( ) } ) , await token . json ( ) ) ;
169+ const signature = await signMessage ( ownerConfig , { account : address , message : challenge } ) ;
170+ const verify = await api . card . $patch ( { json : { method : "siwe" , action : "verify" , message : challenge , signature } } ) ;
171+ if ( ! verify . ok ) throw new APIError ( verify . status , stringOrLegacy ( await verify . json ( ) ) ) ;
172+ }
173+
174+ export async function signCardWebauthn ( ) {
175+ await auth ( ) ;
176+ const credential = await getCredential ( ) ;
177+ const challengeResponse = await api . card . $patch ( { json : { method : "webauthn" , action : "challenge" } } ) ;
178+ if ( ! challengeResponse . ok ) {
179+ throw new APIError ( challengeResponse . status , stringOrLegacy ( await challengeResponse . json ( ) ) ) ;
180+ }
181+ const { challenge } = parse ( object ( { challenge : string ( ) } ) , await challengeResponse . json ( ) ) ;
182+
183+ const assertion = await assert ( {
184+ challenge : bufferToBase64URLString ( hexToBytes ( hashMessage ( challenge ) ) . buffer as ArrayBuffer ) ,
185+ rpId : domain ,
186+ allowCredentials : Platform . OS === "android" ? undefined : [ { id : credential . credentialId , type : "public-key" } ] ,
187+ } ) ;
188+ if ( ! assertion ) throw new Error ( "bad assertion" ) ;
189+ const verify = await api . card . $patch ( { json : { method : "webauthn" , action : "verify" , assertion } } ) ;
190+ if ( ! verify . ok ) throw new APIError ( verify . status , stringOrLegacy ( await verify . json ( ) ) ) ;
191+ }
192+
161193export async function getKYCTokens ( scope : "basic" | "cardLimit" | "manteca" = "basic" , redirectURI ?: string ) {
162194 await auth ( ) ;
163195 const response = await api . kyc . $post ( { json : { scope, redirectURI } } ) ;
0 commit comments