Skip to content

feat: ini same chain #792

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions extras/demo-anypay/src/components/ChooseActionStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as chains from 'viem/chains'
import { SectionHeader } from '@/components/SectionHeader'
import { TokenBalance } from '@0xsequence/anypay-sdk'
import { IntentAction } from '@/types'
import { PAY_CHAIN_ID, PAY_DISPLAY_TEXT } from '@/config'

interface ChooseActionStepProps {
isAutoExecuteEnabled: boolean
Expand Down Expand Up @@ -100,11 +101,11 @@ export const ChooseActionStep: React.FC<ChooseActionStepProps> = ({
'Processing...'
) : (
<>
<NetworkImage chainId={8453} size="sm" className="w-5 h-5" />
<NetworkImage chainId={PAY_CHAIN_ID} size="sm" className="w-5 h-5" />
<span>
Pay Action{' '}
<Text variant="small" color="secondary">
(Donate 0.03 $USDC)
{PAY_DISPLAY_TEXT}
</Text>
</span>
</>
Expand Down
34 changes: 19 additions & 15 deletions extras/demo-anypay/src/components/IntentQuoteDisplayStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ import { getChainInfo } from '@/utils/formatting'
import { IntentAction } from '@/types'
import { Hex, formatUnits, isAddressEqual, zeroAddress } from 'viem'
import { Address as OxAddress } from 'ox'
import * as chains from 'viem/chains'

// Mock Data
const BASE_USDC_DESTINATION_CHAIN_ID = chains.base.id
const RECIPIENT_ADDRESS = '0x750EF1D7a0b4Ab1c97B7A623D7917CcEb5ea779C'
const AMOUNT = 300000n
const MOCK_CONTRACT_ADDRESS = '0x0000000000000000000000000000000000000000'
const MOCK_CHAIN_ID = chains.arbitrum.id
const MOCK_TOKEN_ADDRESS = '0x0000000000000000000000000000000000000000'
const MOCK_TOKEN_AMOUNT = '3000000'
import {
MOCK_CHAIN_ID,
MOCK_CONTRACT_ADDRESS,
MOCK_TOKEN_ADDRESS,
MOCK_TOKEN_AMOUNT,
PAY_AMOUNT,
PAY_CHAIN_ID,
PAY_RECIPIENT_ADDRESS,
PAY_TOKEN_DECIMALS,
PAY_TOKEN_SYMBOL,
} from '@/config'

interface IntentQuoteDisplayStepProps {
createIntentPending: boolean
Expand Down Expand Up @@ -107,15 +108,18 @@ export const IntentQuoteDisplayStep: React.FC<IntentQuoteDisplayStepProps> = ({
if (!intentCallsPayloads || !intentActionType || !selectedToken) return null

if (intentActionType === 'pay') {
const baseChainInfo = getChainInfo(BASE_USDC_DESTINATION_CHAIN_ID)
const baseChainName = baseChainInfo?.name || `Chain ID ${BASE_USDC_DESTINATION_CHAIN_ID}`
const baseChainInfo = getChainInfo(PAY_CHAIN_ID)
const baseChainName = baseChainInfo?.name || `Chain ID ${PAY_CHAIN_ID}`
return (
<>
<Zap className="h-3.5 w-3.5 mr-1.5 text-purple-400 flex-shrink-0" />
Intent: Send <strong className="text-gray-200 mx-1">{formatUnits(AMOUNT, 6)} USDC</strong>
Intent: Send{' '}
<strong className="text-gray-200 mx-1">
{formatUnits(PAY_AMOUNT, PAY_TOKEN_DECIMALS)} {PAY_TOKEN_SYMBOL}
</strong>
to{' '}
<strong className="text-gray-200 font-mono mx-1 truncate max-w-[100px]" title={RECIPIENT_ADDRESS}>
{RECIPIENT_ADDRESS}
<strong className="text-gray-200 font-mono mx-1 truncate max-w-[100px]" title={PAY_RECIPIENT_ADDRESS}>
{PAY_RECIPIENT_ADDRESS}
</strong>
on <strong className="text-gray-200 mx-1">{baseChainName}</strong>
</>
Expand Down
22 changes: 22 additions & 0 deletions extras/demo-anypay/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Hex } from 'viem'
import * as chains from 'viem/chains'

// Mock Data for 'mock_interaction' action
export const MOCK_CONTRACT_ADDRESS = '0x0000000000000000000000000000000000000000'
export const MOCK_TRANSFER_DATA: Hex = `0xabcdef`
export const MOCK_CHAIN_ID = chains.arbitrum.id
export const MOCK_TOKEN_ADDRESS = '0x0000000000000000000000000000000000000000'
export const MOCK_TOKEN_AMOUNT = '3000000'

// Data for 'pay' action
// export const PAY_CHAIN_ID = chains.base.id
export const PAY_CHAIN_ID = chains.arbitrum.id
export const BASE_USDC_PAY_TOKEN_ADDRESS = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'
export const ARB_USDC_PAY_TOKEN_ADDRESS = '0xaf88d065e77c8cc2239327c5edb3a432268e5831'
export const PAY_TOKEN_ADDRESS = ARB_USDC_PAY_TOKEN_ADDRESS
export const PAY_TOKEN_SYMBOL = 'USDC'
export const PAY_TOKEN_DECIMALS = 6
export const PAY_RECIPIENT_ADDRESS = '0x750EF1D7a0b4Ab1c97B7A623D7917CcEb5ea779C'
export const PAY_AMOUNT = 300000n // 0.3 USDC
export const PAY_AMOUNT_FORMATTED = '0.3'
export const PAY_DISPLAY_TEXT = `(Donate $${PAY_AMOUNT_FORMATTED} ${PAY_TOKEN_SYMBOL})`
48 changes: 19 additions & 29 deletions extras/demo-anypay/src/routes/home/home-index-route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useState, useEffect } from 'react'
import { useAccount, useConnect, useDisconnect } from 'wagmi'
import { Hex } from 'viem'
import { AbiFunction, Address } from 'ox'
import * as chains from 'viem/chains'
import { useAnyPay, useTokenBalances, TokenBalance, Account } from '@0xsequence/anypay-sdk'
import { Loader2 } from 'lucide-react'
import { AccountInfoSection } from '@/components/AccountInfoSection'
Expand All @@ -14,26 +13,17 @@ import { CommitIntentStep } from '@/components/CommitIntentStep'
import { OriginCallStep } from '@/components/OriginCallStep'
import { AdvancedControlsSection } from '@/components/AdvancedControlsSection'
import { RelayerStatusSection } from '@/components/RelayerStatusSection'

// Mock Data
const MOCK_CONTRACT_ADDRESS = '0x0000000000000000000000000000000000000000'
// Mock Calldata for interaction
const MOCK_TRANSFER_DATA: Hex = `0xabcdef`
// Mock Chain ID for interaction
const MOCK_CHAIN_ID = chains.arbitrum.id
// Mock Token Address for interaction on destination chain
const MOCK_TOKEN_ADDRESS = '0x0000000000000000000000000000000000000000'
// Mock Token Amount for interaction on destination chain
const MOCK_TOKEN_AMOUNT = '3000000'

// Chain ID for destination chain (base)
const BASE_USDC_DESTINATION_CHAIN_ID = chains.base.id
// USDC Address for interaction on destination chain (base)
const BASE_USDC_ADDRESS = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'
// Give Directly - recipient Address for interaction on destination chain (base)
const RECIPIENT_ADDRESS = '0x750EF1D7a0b4Ab1c97B7A623D7917CcEb5ea779C'
// Amount of USDC to transfer on destination chain (base)
const AMOUNT = 30000n // 0.03 USDC (6 decimals)
import {
MOCK_CONTRACT_ADDRESS,
MOCK_TRANSFER_DATA,
MOCK_CHAIN_ID,
MOCK_TOKEN_ADDRESS,
MOCK_TOKEN_AMOUNT,
PAY_CHAIN_ID,
PAY_TOKEN_ADDRESS,
PAY_RECIPIENT_ADDRESS,
PAY_AMOUNT,
} from '@/config'

function useHook() {
const account = useAccount()
Expand All @@ -46,9 +36,9 @@ function useHook() {
to: '',
data: '',
value: '0',
chainId: BASE_USDC_DESTINATION_CHAIN_ID.toString(),
chainId: PAY_CHAIN_ID.toString(),
tokenAmount: '0',
tokenAddress: BASE_USDC_ADDRESS,
tokenAddress: PAY_TOKEN_ADDRESS,
})

const {
Expand Down Expand Up @@ -115,14 +105,14 @@ function useHook() {
if (action === 'pay') {
// ERC20 ABI functions
const erc20Transfer = AbiFunction.from('function transfer(address,uint256) returns (bool)')
const encodedData = AbiFunction.encodeData(erc20Transfer, [RECIPIENT_ADDRESS, AMOUNT]) as Hex
const encodedData = AbiFunction.encodeData(erc20Transfer, [PAY_RECIPIENT_ADDRESS, PAY_AMOUNT]) as Hex

// Ensure calldata is prefixed with 0x
const transactionData = encodedData.startsWith('0x') ? encodedData : `0x${encodedData}`

destinationCall = {
chainId: BASE_USDC_DESTINATION_CHAIN_ID,
to: BASE_USDC_ADDRESS,
chainId: PAY_CHAIN_ID,
to: PAY_TOKEN_ADDRESS,
transactionData,
transactionValue: '0',
}
Expand All @@ -141,7 +131,7 @@ function useHook() {

destinationCall = {
chainId: destinationChainId,
to: BASE_USDC_ADDRESS,
to: PAY_TOKEN_ADDRESS,
transactionData,
transactionValue: '0',
}
Expand Down Expand Up @@ -171,13 +161,13 @@ function useHook() {
? customCallData.tokenAddress
: action === 'mock_interaction'
? MOCK_TOKEN_ADDRESS
: BASE_USDC_ADDRESS,
: PAY_TOKEN_ADDRESS,
destinationTokenAmount:
action === 'custom_call'
? customCallData.tokenAmount
: action === 'mock_interaction'
? MOCK_TOKEN_AMOUNT
: AMOUNT.toString(),
: PAY_AMOUNT.toString(),
destinationCallData:
action === 'custom_call'
? customCallData.data.startsWith('0x')
Expand Down
10 changes: 9 additions & 1 deletion packages/wallet/anypay-sdk/src/anypay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,12 @@ export function useAnyPay(config: UseAnyPayConfig): UseAnyPayReturn {
// TODO: Add type for args
const createIntentMutation = useMutation<GetIntentCallsPayloadsReturn, Error, GetIntentCallsPayloadsArgs>({
mutationFn: async (args: GetIntentCallsPayloadsArgs) => {
if (
args.originChainId === args.destinationChainId &&
isAddressEqual(Address.from(args.originTokenAddress), Address.from(args.destinationTokenAddress))
) {
throw new Error('The same token cannot be used as both the source and destination token.')
}
if (!account.address) {
throw new Error('Missing selected token or account address')
}
Expand Down Expand Up @@ -1258,6 +1264,7 @@ type SendOptions = {
recipient: string
destinationTokenAddress: string
destinationTokenAmount: string
destinationTokenSymbol: string
sequenceApiKey: string
fee: string
client?: WalletClient
Expand All @@ -1278,6 +1285,7 @@ export async function prepareSend(options: SendOptions) {
recipient,
destinationTokenAddress,
destinationTokenAmount,
destinationTokenSymbol,
sequenceApiKey,
fee,
client,
Expand All @@ -1294,7 +1302,7 @@ export async function prepareSend(options: SendOptions) {
userAddress: mainSigner,
originChainId,
originTokenAddress,
originTokenAmount, // max amount
originTokenAmount: originTokenAddress === destinationTokenAddress ? destinationTokenAmount : originTokenAmount,
destinationChainId,
destinationToAddress: destinationTokenAddress == zeroAddress ? recipient : destinationTokenAddress,
destinationTokenAddress: destinationTokenAddress,
Expand Down
5 changes: 5 additions & 0 deletions packages/wallet/anypay-sdk/src/intents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ export async function sendOriginTransaction(
client: WalletClient,
originParams: SendOriginCallTxArgs,
): Promise<`0x${string}`> {
const chainId = await client.getChainId()
if (chainId !== originParams.chain.id) {
await client.switchChain({ id: originParams.chain.id })
}

const hash = await client.sendTransaction({
account: wallet,
to: originParams.to as `0x${string}`,
Expand Down
10 changes: 6 additions & 4 deletions packages/wallet/anypay-sdk/src/widget/components/SendForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useRef, useEffect } from 'react'
import React, { useState, useRef, useEffect, useMemo } from 'react'

import { NetworkImage, TokenImage } from '@0xsequence/design-system'
import * as chains from 'viem/chains'
import { createWalletClient, custom, formatUnits, parseUnits, type Account } from 'viem'
Expand Down Expand Up @@ -124,7 +125,7 @@ export const SendForm: React.FC<SendFormProps> = ({
const {
data: ensAddress,
isLoading,
error,
error: ensError,
} = useEnsAddress({
name: recipientInput.endsWith('.eth') ? recipientInput : undefined,
chainId: mainnet.id,
Expand Down Expand Up @@ -183,7 +184,7 @@ export const SendForm: React.FC<SendFormProps> = ({
const client = createWalletClient({
account,
chain: getChainConfig(selectedToken.chainId),
transport: custom(window.ethereum),
transport: custom((window as any).ethereum),
})

console.log('selectedDestToken.symbol', selectedDestToken)
Expand All @@ -204,8 +205,9 @@ export const SendForm: React.FC<SendFormProps> = ({
? zeroAddress
: getDestTokenAddress(selectedChain.id, selectedDestToken.symbol),
destinationTokenAmount: parsedAmount,
destinationTokenSymbol: selectedDestToken.symbol,
sequenceApiKey,
fee: selectedToken.symbol === 'ETH' ? parseUnits('0.0001', 18).toString() : parseUnits('0.02', 6).toString(), // TOOD: fees
fee: '0',
client,
apiClient,
originRelayer,
Expand Down
Loading