@@ -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" ] , {
@@ -157,6 +158,37 @@ export async function setCardPIN(pin: string) {
157158 if ( ! response . ok ) throw new APIError ( response . status , stringOrLegacy ( await response . json ( ) ) ) ;
158159}
159160
161+ export async function signCard ( ) {
162+ await auth ( ) ;
163+ const address = getConnection ( ownerConfig ) . address ;
164+ if ( ! address ) throw new Error ( "no owner wallet connected" ) ;
165+ const token = await api . card . $patch ( { json : { method : "siwe" , action : "challenge" } } ) ;
166+ if ( ! token . ok ) throw new APIError ( token . status , stringOrLegacy ( await token . json ( ) ) ) ;
167+ const { challenge } = parse ( object ( { challenge : string ( ) } ) , await token . json ( ) ) ;
168+ const signature = await signMessage ( ownerConfig , { account : address , message : challenge } ) ;
169+ const verify = await api . card . $patch ( { json : { method : "siwe" , action : "verify" , message : challenge , signature } } ) ;
170+ if ( ! verify . ok ) throw new APIError ( verify . status , stringOrLegacy ( await verify . json ( ) ) ) ;
171+ }
172+
173+ export async function signCardWebauthn ( ) {
174+ await auth ( ) ;
175+ const credential = await getCredential ( ) ;
176+ const challengeResponse = await api . card . $patch ( { json : { method : "webauthn" , action : "challenge" } } ) ;
177+ if ( ! challengeResponse . ok ) {
178+ throw new APIError ( challengeResponse . status , stringOrLegacy ( await challengeResponse . json ( ) ) ) ;
179+ }
180+ const { challenge } = parse ( object ( { challenge : string ( ) } ) , await challengeResponse . json ( ) ) ;
181+
182+ const assertion = await assert ( {
183+ challenge : bufferToBase64URLString ( hexToBytes ( hashMessage ( challenge ) ) . buffer as ArrayBuffer ) ,
184+ rpId : domain ,
185+ allowCredentials : Platform . OS === "android" ? undefined : [ { id : credential . credentialId , type : "public-key" } ] ,
186+ } ) ;
187+ if ( ! assertion ) throw new Error ( "bad assertion" ) ;
188+ const verify = await api . card . $patch ( { json : { method : "webauthn" , action : "verify" , assertion } } ) ;
189+ if ( ! verify . ok ) throw new APIError ( verify . status , stringOrLegacy ( await verify . json ( ) ) ) ;
190+ }
191+
160192export async function getKYCTokens ( scope : "basic" | "cardLimit" | "manteca" = "basic" , redirectURI ?: string ) {
161193 await auth ( ) ;
162194 const response = await api . kyc . $post ( { json : { scope, redirectURI } } ) ;
0 commit comments