import {z} from 'zod' export type TransactionID = string; export type CreateApiTxAcceptArgs = {id: TransactionID}; export type CreateApiTxAcceptOptions = {baseUrl?: string | undefined, bearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const transactionID = z.string(); export const transactionStatus = z.enum(["SAVED", "MISSING_BENEFICIARY_DATA", "NEW", "WAITING_FOR_INFORMATION", "SENT", "REJECTED", "DECLINED", "ACK", "CANCELLED", "INCOMPLETE", "ACCEPTED", "NOT_READY"]); export const transactionType = z.enum(["BELOW_THRESHOLD", "NON_CUSTODIAL", "TRAVELRULE", "UNKNOWN"]); export const commonDID = z.string(); export const transactionBlockchainInfo = z.object({txHash: z.string().optional(), origin: z.string().optional(), destination: z.string()}); export const text = z.string(); export const naturalPersonNameTypeCode = z.enum(["ALIA", "BIRT", "MAID", "LEGL", "MISC"]); export const naturalPersonNameID = z.object({primaryIdentifier: text.optional(), secondaryIdentifier: text.optional(), nameIdentifierType: naturalPersonNameTypeCode.optional()}); export const localNaturalPersonNameID = z.object({primaryIdentifier: text.optional(), secondaryIdentifier: text.optional(), nameIdentifierType: naturalPersonNameTypeCode.optional()}); export const naturalPersonName = z.object({nameIdentifier: z.array(naturalPersonNameID), localNameIdentifier: z.array(localNaturalPersonNameID).optional(), phoneticNameIdentifier: z.array(localNaturalPersonNameID).optional()}); export const addressTypeCode = z.enum(["HOME", "BIZZ", "GEOG"]); export const ivms101CountryCode = z.string(); export const ivms101Address = z.object({addressType: addressTypeCode.optional(), department: text.optional(), subDepartment: text.optional(), streetName: text.optional(), buildingNumber: text.optional(), buildingName: text.optional(), floor: text.optional(), postBox: text.optional(), room: text.optional(), postCode: text.optional(), townName: text.optional(), townLocationName: text.optional(), districtName: text.optional(), countrySubDivision: text.optional(), addressLine: z.array(text).optional(), country: ivms101CountryCode.optional()}); export const nationalIdentifierTypeCode = z.enum(["ARNU", "CCPT", "RAID", "DRLC", "FIIN", "TXID", "SOCS", "IDCD", "LEIX", "MISC"]); export const nationalIdentification = z.object({nationalIdentifier: text, nationalIdentifierType: nationalIdentifierTypeCode, countryOfIssue: ivms101CountryCode.optional(), registrationAuthority: text.optional()}); export const date = z.string(); export const dateAndPlaceOfBirth = z.object({dateOfBirth: date, placeOfBirth: text}); export const naturalPerson = z.object({name: z.array(naturalPersonName), geographicAddress: z.array(ivms101Address).optional(), nationalIdentification: nationalIdentification.optional(), customerIdentification: text.optional(), dateAndPlaceOfBirth: dateAndPlaceOfBirth.optional(), countryOfResidence: ivms101CountryCode.optional()}); export const legalPersonNameTypeCode = z.enum(["LEGL", "SHRT", "TRAD"]); export const legalPersonNameID = z.object({legalPersonName: text.optional(), legalPersonNameIdentifierType: legalPersonNameTypeCode.optional()}); export const localLegalPersonNameID = z.object({legalPersonName: text.optional(), legalPersonNameIdentifierType: legalPersonNameTypeCode.optional()}); export const legalPersonName = z.object({nameIdentifier: z.array(legalPersonNameID), localNameIdentifier: z.array(localLegalPersonNameID).optional(), phoneticNameIdentifier: z.array(localLegalPersonNameID).optional()}); export const legalPerson = z.object({name: legalPersonName, geographicAddress: z.array(ivms101Address).optional(), customerNumber: text.optional(), nationalIdentification: nationalIdentification.optional(), dateOfRegistration: date.optional(), countryOfRegistration: ivms101CountryCode.optional()}); export const ivms101Person = z.object({naturalPerson: naturalPerson.optional(), legalPerson: legalPerson.optional()}); export const ivms101Originator = z.object({originatorPersons: z.array(ivms101Person), accountNumber: z.array(text).optional()}); export const ivms101Beneficiary = z.object({beneficiaryPersons: z.array(ivms101Person), accountNumber: z.array(text).optional()}); export const originatingVASP = z.object({originatingVASP: ivms101Person.optional()}); export const beneficiaryVASP = z.object({beneficiaryVASP: ivms101Person.optional()}); export const ivms101Number = z.number().int(); export const intermediaryVASP = z.object({intermediaryVASP: ivms101Person, sequence: ivms101Number}); export const transferPath = z.object({transferPath: z.array(intermediaryVASP).optional()}); export const transliterationMethodCode = z.enum(["arab", "aran", "armn", "cyrl", "deva", "geor", "grek", "hani", "hebr", "kana", "kore", "thai", "othr"]); export const payloadMetadata = z.object({transliterationMethod: z.array(transliterationMethodCode).optional()}); export const ivms101IVMS101 = z.object({originator: ivms101Originator.optional(), beneficiary: ivms101Beneficiary.optional(), originatingVASP: originatingVASP.optional(), beneficiaryVASP: beneficiaryVASP.optional(), transferPath: transferPath.optional(), payloadMetadata: payloadMetadata.optional()}); export const trTravelRuleProtocol = z.enum(["TRLight", "TRP", "OpenVASP"]); export const protocolData = z.object({trLightData: z.object({notificationEmails: z.array(z.string()).optional()}).optional()}); export const ownershipProof = z.union([z.object({type: z.enum(["eip-191", "eip-712", "bip-137"]), proof: z.string(), attestation: z.string(), address: z.string().optional(), status: z.string().optional()}), z.object({type: z.literal("screenshot"), url: z.string()}), z.object({type: z.literal("self-declaration"), did: z.string().optional(), address: z.string().optional(), attestation: z.string(), confirmed: z.boolean().optional(), status: z.string().optional()}), z.object({type: z.literal("microtransfer"), did: z.string().optional(), address: z.string().optional(), proof: z.string(), chain: z.string().optional(), destination: z.string().optional(), amountSubunits: z.string().optional(), status: z.string().optional()}), z.object({type: z.string()}).and(z.record(z.string(), z.unknown()))]); export const transactionAction = z.object({hash: z.string().optional(), issuerDID: commonDID.optional(), action: z.string().optional(), actionData: z.string().optional()}); export const piiNaturalPersonNameID = z.object({primaryIdentifier: text.optional(), secondaryIdentifier: text.optional(), nameIdentifierType: text.optional()}); export const piiLocalNaturalPersonNameID = z.object({primaryIdentifier: text.optional(), secondaryIdentifier: text.optional(), nameIdentifierType: text.optional()}); export const piiNaturalPersonName = z.object({nameIdentifier: z.array(piiNaturalPersonNameID), localNameIdentifier: z.array(piiLocalNaturalPersonNameID).optional(), phoneticNameIdentifier: z.array(piiLocalNaturalPersonNameID).optional()}); export const piiAddress = z.object({addressType: text.optional(), department: text.optional(), subDepartment: text.optional(), streetName: text.optional(), buildingNumber: text.optional(), buildingName: text.optional(), floor: text.optional(), postBox: text.optional(), room: text.optional(), postCode: text.optional(), townName: text.optional(), townLocationName: text.optional(), districtName: text.optional(), countrySubDivision: text.optional(), addressLine: z.array(text).optional(), country: text.optional()}); export const piiNationalIdentification = z.object({nationalIdentifier: text, nationalIdentifierType: text, countryOfIssue: text.optional(), registrationAuthority: text.optional()}); export const piiDateAndPlaceOfBirth = z.object({dateOfBirth: text, placeOfBirth: text}); export const piiNaturalPerson = z.object({name: z.array(piiNaturalPersonName), geographicAddress: z.array(piiAddress).optional(), nationalIdentification: piiNationalIdentification.optional(), customerIdentification: text.optional(), dateAndPlaceOfBirth: piiDateAndPlaceOfBirth.optional(), countryOfResidence: text.optional()}); export const piiLegalPersonNameID = z.object({legalPersonName: text.optional(), legalPersonNameIdentifierType: text.optional()}); export const piiLocalLegalPersonNameID = z.object({legalPersonName: text.optional(), legalPersonNameIdentifierType: text.optional()}); export const piiLegalPersonName = z.object({nameIdentifier: z.array(piiLegalPersonNameID), localNameIdentifier: z.array(piiLocalLegalPersonNameID).optional(), phoneticNameIdentifier: z.array(piiLocalLegalPersonNameID).optional()}); export const piiLegalPerson = z.object({name: piiLegalPersonName, geographicAddress: z.array(piiAddress).optional(), customerNumber: text.optional(), nationalIdentification: piiNationalIdentification.optional(), dateOfRegistration: text.optional(), countryOfRegistration: text.optional()}); export const piiPerson = z.object({naturalPerson: piiNaturalPerson.optional(), legalPerson: piiLegalPerson.optional()}); export const piiOriginator = z.object({originatorPersons: z.array(piiPerson), accountNumber: z.array(text).optional()}); export const piiBeneficiary = z.object({beneficiaryPersons: z.array(piiPerson), accountNumber: z.array(text).optional()}); export const piiOriginatingVASP = z.object({originatingVASP: piiPerson.optional()}); export const piiBeneficiaryVASP = z.object({beneficiaryVASP: piiPerson.optional()}); export const piiIntermediaryVASP = z.object({intermediaryVASP: piiPerson, sequence: text}); export const piiTransferPath = z.object({transferPath: z.array(piiIntermediaryVASP).optional()}); export const piiPayloadMetadata = z.object({transliterationMethod: z.array(text).optional()}); export const pIIIVMS = z.object({originator: piiOriginator.optional(), beneficiary: piiBeneficiary.optional(), originatingVASP: piiOriginatingVASP.optional(), beneficiaryVASP: piiBeneficiaryVASP.optional(), transferPath: piiTransferPath.optional(), payloadMetadata: piiPayloadMetadata.optional()}); export const transaction = z.object({id: transactionID, status: transactionStatus.optional(), transactionType: transactionType, transactionAsset: z.string(), transactionAmount: z.string(), chargedQuantity: z.number(), amountInLocalCurrency: z.object({amountInLocalCurrency: z.number().optional(), currency: z.string().optional()}).optional(), beneficiaryAmountInLocalCurrency: z.object({amountInLocalCurrency: z.number().optional(), currency: z.string().optional()}).optional(), originatorDid: commonDID.optional(), beneficiaryDid: commonDID, originatorVASPdid: commonDID.optional(), beneficiaryVASPdid: commonDID.optional(), transactionBlockchainInfo: transactionBlockchainInfo.optional(), ivms101: ivms101IVMS101.optional(), ivms101Encrypted: z.string().optional(), protocol: trTravelRuleProtocol.optional(), protocolData: protocolData.optional(), originatorProof: ownershipProof.optional(), beneficiaryProof: ownershipProof.optional(), actions: z.array(transactionAction).optional(), pii: pIIIVMS.optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Accept transfer * * POST /tx/accept */ export const createApiTxAccept = async (args: CreateApiTxAcceptArgs, options?: CreateApiTxAcceptOptions) => { const {baseUrl = "https://api.eu1.notabene.id", fetch: fetchFn = fetch, bearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.id != null) query.append("id", String(args.id)) if (bearerAuth !== undefined) headers.set('authorization', `Bearer ${bearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/tx/accept${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(transaction, await res.json()) };