Skip to content

Commit

Permalink
v1.1: deserialize txs and use native types
Browse files Browse the repository at this point in the history
  • Loading branch information
mPaella committed Sep 14, 2023
1 parent a20e808 commit b62a4b6
Show file tree
Hide file tree
Showing 9 changed files with 452 additions and 39 deletions.
6 changes: 4 additions & 2 deletions packages/core/base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
},
"dependencies": {
"exponential-backoff": "3.1.1",
"uuid": "9.0.0"
"uuid": "9.0.1"
},
"devDependencies": {
"@types/uuid": "9.0.3"
"@ethersproject/transactions": "5.7.0",
"@solana/web3.js": "1.78.5",
"@types/uuid": "9.0.4"
}
}
32 changes: 22 additions & 10 deletions packages/core/base/src/types/embed/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
import type { Transaction as EthersTransaction } from "@ethersproject/transactions";
import type { Transaction as SolanaTransaction } from "@solana/web3.js";

import { CommonEmbeddedCheckoutProps } from ".";
import { CryptoPaymentMethod } from "..";
import { CryptoPaymentMethod, RequiredBy } from "..";

export type CryptoEmbeddedCheckoutProps<
type CryptoEmbeddedCheckoutPropsBase<
PM extends keyof CryptoPaymentMethodSignerMap = keyof CryptoPaymentMethodSignerMap,
> = CommonEmbeddedCheckoutProps<PM> & {
signer?: CryptoPaymentMethodSignerMap[PM];
};

export type CryptoEmbeddedCheckoutPropsWithSigner<
type CryptoEmbeddedCheckoutPropsWithSignerBase<
PM extends keyof CryptoPaymentMethodSignerMap = keyof CryptoPaymentMethodSignerMap,
> = CommonEmbeddedCheckoutProps<PM> & {
signer: CryptoPaymentMethodSignerMap[PM];
};
> = RequiredBy<CryptoEmbeddedCheckoutPropsBase<PM>, "signer">;

// Union discriminate with required signer
export type CryptoEmbeddedCheckoutPropsWithSigner = {
[PM in keyof CryptoPaymentMethodSignerMap]: CryptoEmbeddedCheckoutPropsWithSignerBase<PM>;
}[keyof CryptoPaymentMethodSignerMap];

// Union discriminate type - both with or without signer
export type CryptoEmbeddedCheckoutProps =
| {
[PM in keyof CryptoPaymentMethodSignerMap]: CryptoEmbeddedCheckoutPropsBase<PM>;
}[keyof CryptoPaymentMethodSignerMap]
| CryptoEmbeddedCheckoutPropsWithSigner;

type CryptoPaymentMethodSignerMap = {
export type CryptoPaymentMethodSignerMap = {
[CryptoPaymentMethod.ETH]: ETHEmbeddedCheckoutSigner;
[CryptoPaymentMethod.SOL]: SOLEmbeddedCheckoutSigner;
};
Expand All @@ -23,11 +36,10 @@ type CommonEmbeddedCheckoutSignerProps = {
};

// Signers
// TODO: Import proper types from respective packages
export type ETHEmbeddedCheckoutSigner = CommonEmbeddedCheckoutSignerProps & {
signAndSendTransaction: (transaction: any) => Promise<string>;
signAndSendTransaction: (transaction: EthersTransaction) => Promise<string>;
};

export type SOLEmbeddedCheckoutSigner = CommonEmbeddedCheckoutSignerProps & {
signAndSendTransaction: (transaction: any) => Promise<string>;
signAndSendTransaction: (transaction: SolanaTransaction) => Promise<string>;
};
2 changes: 1 addition & 1 deletion packages/core/base/src/types/embed/fiat.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CommonEmbeddedCheckoutProps } from ".";

export type FiatEmbeddedCheckoutProps = CommonEmbeddedCheckoutProps<"fiat"> & {
export type FiatEmbeddedCheckoutProps = CommonEmbeddedCheckoutProps<"fiat" | undefined> & {
// TODO: Audit old params
cardWalletPaymentMethods?: CardWalletPaymentMethod | CardWalletPaymentMethod[] | "none";
emailInputOptions?: EmailInputOptions;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/base/src/types/embed/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import { FiatEmbeddedCheckoutProps } from "./fiat";
export * from "./crypto";
export * from "./fiat";

export type CommonEmbeddedCheckoutProps<PM extends PaymentMethod = PaymentMethod> = {
paymentMethod?: PM;
export type CommonEmbeddedCheckoutProps<PM extends PaymentMethod | undefined = PaymentMethod | undefined> = {
paymentMethod: PM;
mintConfig?: MintConfigs;
currency?: CaseInsensitive<Currency>;
locale?: Locale;
Expand Down
3 changes: 3 additions & 0 deletions packages/core/base/src/types/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ export type TypeFromPath<

export type CaseInsensitive<T extends string> = T | Uppercase<T> | Lowercase<T>;
export type EmptyObject = Record<string, never>;

export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
export type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
6 changes: 3 additions & 3 deletions packages/starter/nextjs-starter/pages/payment-element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ export default function PaymentElementPage() {
}}
paymentMethod="ETH"
signer={{
address: "0xdC9bb9929b79b62d630A7C3568c979a2843eFd8b",
signAndSendTransaction: async (tx) => {
return "0x1234";
address: "maxfQWBno84Zfu4sXgmjYvsvLn4LzGFSgSkFMFuzved",
signAndSendTransaction: async (transaction) => {
return "123";
},
}}
onEvent={(event) => {
Expand Down
3 changes: 3 additions & 0 deletions packages/ui/react-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
},
"dependencies": {
"@crossmint/client-sdk-base": "1.1.0-alpha.0",
"@ethersproject/transactions": "5.7.0",
"@solana/web3.js": "1.78.5",
"bs58": "5.0.0",
"react-jss": "10.10.0"
},
"peerDependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import bs58 from "bs58";

import {
CryptoEmbeddedCheckoutPropsWithSigner,
ETHEmbeddedCheckoutSigner,
IncomingInternalEvent,
SOLEmbeddedCheckoutSigner,
crossmintIFrameService,
} from "@crossmint/client-sdk-base";

Expand All @@ -9,20 +13,31 @@ import CrossmintEmbeddedCheckoutIFrame from "../EmbeddedCheckoutIFrame";
export default function CryptoEmbeddedCheckoutIFrame(props: CryptoEmbeddedCheckoutPropsWithSigner) {
const { emitInternalEvent } = crossmintIFrameService(props);

const { signer } = props;
const { signer, paymentMethod } = props;

function onInternalEvent(event: IncomingInternalEvent) {
const { type, payload } = event;

if (type === "crypto-payment:incoming-transaction") {
const { serializedTransaction } = payload;
console.log("[Crossmint] Received incoming transaction", serializedTransaction);
handleIncomingTransaction(serializedTransaction);
}
}

async function handleIncomingTransaction(serializedTransaction: string) {
try {
const txId = await signer.signAndSendTransaction(serializedTransaction);
let txId: string;
switch (paymentMethod) {
case "SOL":
txId = await handleSOLTransaction(signer, serializedTransaction);
break;
case "ETH":
txId = await handleETHTransaction(signer, serializedTransaction);
break;
default:
throw new Error(`Unsupported payment method ${paymentMethod}`);
}

console.log("[Crossmint] Signed and sent transaction", txId);
emitInternalEvent({
Expand All @@ -40,5 +55,23 @@ export default function CryptoEmbeddedCheckoutIFrame(props: CryptoEmbeddedChecko
}
}

async function handleSOLTransaction(signer: SOLEmbeddedCheckoutSigner, serializedTransaction: string) {
// @ts-expect-error - Error becasue we dont use 'module' field in tsconfig, which is expected because we use tsup to compile
const { Transaction } = await import("@solana/web3.js");
const transaction = Transaction.from(bs58.decode(serializedTransaction));
console.log("[Crossmint] Deserialized SOL transaction", transaction);

return await signer.signAndSendTransaction(transaction);
}

async function handleETHTransaction(signer: ETHEmbeddedCheckoutSigner, serializedTransaction: string) {
// @ts-expect-error - Error becasue we dont use 'module' field in tsconfig, which is expected because we use tsup to compile
const { parse: parseTransaction } = await import("@ethersproject/transactions");
const transaction = parseTransaction(serializedTransaction);
console.log("[Crossmint] Deserialized ETH transaction", transaction);

return await signer.signAndSendTransaction(transaction);
}

return <CrossmintEmbeddedCheckoutIFrame onInternalEvent={onInternalEvent} {...props} />;
}
Loading

0 comments on commit b62a4b6

Please sign in to comment.