Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

paykit: create payments directly from the button #15

Merged
merged 6 commits into from
Dec 27, 2024
Merged

paykit: create payments directly from the button #15

merged 6 commits into from
Dec 27, 2024

Conversation

dcposch
Copy link
Member

@dcposch dcposch commented Dec 23, 2024

Basic

image
<DaimoPayButton
  appId={APP_ID}
  toChain={8453}
  toAddress="0xFBfa6A0D1F44b60d7CCA4b95d5a2CfB15246DB0D"
  toAmount={120000n}
  toToken={getAddress(baseUSDC.token)}
  onPaymentStarted={printEvent}
  onPaymentCompleted={printEvent}
/>

Contract

image
  <DaimoPayButton
      appId={APP_ID}
      toChain={8453}
      toAddress="0xFBfa6A0D1F44b60d7CCA4b95d5a2CfB15246DB0D"
      toAmount={parseUnits("0.0001", 18)} /* 10^-4 ETH */
      toToken={zeroAddress} /* Zero address = ETH */
      toCallData={encodeFunctionData({
        abi: parseAbi([
          "function placePrediction(uint256, uint256) external",
        ]),
        functionName: "placePrediction",
        args: [1n, 2n],
      })}
      onPaymentStarted={printEvent}
      onPaymentCompleted={printEvent}
      onPaymentBounced={printEvent}
  />

Checkout

image

Pregenerated payID:

  const [payId, setPayId] = useState<string>();
  useEffect(() => {
    const payId = generatePayId();
    // Save payId to your backend here. This ensures that you'll be able to
    // correlate all incoming payments even if the user loses network, etc.
    // await saveCartCheckout(payId, ...);
    setPayId(payId);
  }, []);
    
  <DaimoPayButton
    appId={APP_ID}
    newPayId={payId}
    toChain={8453}
    toAddress="0xFBfa6A0D1F44b60d7CCA4b95d5a2CfB15246DB0D"
    toAmount={420000n} /* $0.42 USDC */
    toToken={getAddress(baseUSDC.token)}
    preferredChains={[8453]}
    preferredTokens={[{ chain: 8453, address: getAddress(baseDAI.token) }]}
  />

@dcposch dcposch marked this pull request as ready for review December 24, 2024 21:23
/**
* Optional nonce. If set, generates a deterministic payID. See docs.
*/
nonce?: bigint;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the nonce as in destNonce onchain? Currently we always set nonce = payID onchain, and it's a nice invariant to enforce that the create2 parameters are publicly known by all parties. I'd recommend keeping that / not providing this option perhaps?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invariant is still there. if you provide the nonce, that becomes the id. (Wrote "generates a determinstic payID" to avoid confusion because our payIds are formatted in base58.)

Copy link
Member Author

@dcposch dcposch Dec 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

example use case in DonateForm:

  • generate nonce
  • on click, save (form info, payment nonce)
  • then show checkout modal

this creates a guarantee that every payment is attributed.

--

maybe there's a cleaner way to support that.

we could usenewPayId instead of nonce, and we provide a utility function createRandomPayId that returns the base58 form

then we don't have to expose concept of "nonce" in SDK

lmk if that feels cleaner

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update to use newPayId to reduce confusion

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted newPayId, just using onPaymentStarted for now

/**
* Optional calldata to call an arbitrary function on `toAddress`.
*/
toCallData?: Hex;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should all of these be folded into a recipient?

recipient: {
    address: `0x..`,
    tokenAddress: `0x..`,
    amount: 123n,
    calldata: `0x..`,
}

Makes it easier in future if we have something like "Allowed recipients" to add a recipient: {id: "1234.."} option

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allowed recipients might be just the contracts (address + chain ID), right?

the calldata and amount still has to vary payment to payment. eg ethOS would whitelist their minting contract on Base.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one other place where IDs would be useful is bank accounts.

some ideas

Send $20.00 to a bank account

recipient={{
  id: "06b0e3e3-91a6-4b09-bffe-46eab58ffa18",
  currency: "USD",
  quantity: "20.00"
}}

vs

toAccount="06b0e3e3-91a6-4b09-bffe-46eab58ffa18"
toCurrency="USD"
toQuantity="20.00"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated. using toUnits to match Viem convention

/**
* Preferred chain IDs. Assets on these chains will appear first.
*/
preferredChains?: number[];
Copy link
Member

@nalinbhardwaj nalinbhardwaj Dec 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no preferredToken? fine if no one needs it but I actually thought that was the one people like ethOS wanted (and this one hasn't been used by anyone yet)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added.

const { paymentState } = context;
useEffect(
() => {
if ("payId" in props) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think this is ever true? how does this work

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we still support <DaimoPayButton payId={...} /> used eg. for our own hosted page

address?: Hash;
truncatedAddress?: string;
ensName?: string;
payId?: string;
Copy link
Member

@nalinbhardwaj nalinbhardwaj Dec 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need payId and intent if we put text in the button from the payment?

Copy link
Member Author

@dcposch dcposch Dec 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with the new style, the payment isn't saved till hydration. we do generate what the payId will be, but might be confusing to pass thru payId that doesn't exist when looked up in API

can pass thru intent, but this is the client's own page, right? say they make a custom Donate button + make the payment with intent=Donate so modal shows nicely

@@ -56,17 +56,12 @@ function getDepositAddressOption(depositAddressOptions: {
}) {
const { setRoute } = usePayContext();

console.log(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log?

trpc.processSolanaSourcePayment.mutate({
orderId: orderId.toString(),
startIntentTxHash: txHash,
amount: chosenFinalTokenAmount,
amount: "0", // TODO: replace.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the best way to get the amount of input token sent from the txHash (not sure how receipts work on Solana... do they have something like the Transfer event log we can fetch?)

  • we are using an exact-output swap, so we don't know how much input token will be consumed upfront, only once it's onchain
  • the previous code was substituting a totally different amount (different token, different decimals) as far as i can tell

Comment on lines 16 to 17
// These first two just return configured wagmi chains = not necessarily
// supported by Daimo Pay.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? If dev uses getDefaultConfig as we intend them to those are equivalent?

*/
preferredChains?: number[];
}
| {
Copy link
Member

@nalinbhardwaj nalinbhardwaj Dec 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should put functional onPaymentStarted, onPaymentCompleted, onPaymentBounced etc here? Currently if the modal generates a payment, the dev has no way to obtain the ID afaict? (they may want to track it in their backend / webhooks etc later)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100%, coming soon.

@dcposch dcposch force-pushed the dc/sdk branch 2 times, most recently from d6de290 to b6963e6 Compare December 27, 2024 13:18
Copy link

socket-security bot commented Dec 27, 2024

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/[email protected] environment +4 2.59 MB ai

View full report↗︎

@dcposch
Copy link
Member Author

dcposch commented Dec 27, 2024

Solana amount tracking works now

a bugfix shipping with this PR:

Screenshot 2024-12-27 at 05 23 38 image

.. 1.4778 is the amount sent into the exactOutput swap, recovered from the transaction receipt

@dcposch
Copy link
Member Author

dcposch commented Dec 27, 2024

Token sort working again

Looks like it was broken for a while in prod. Bugfixed.

@dcposch dcposch merged commit db93f56 into main Dec 27, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants