Skip to content
Draft
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
82 changes: 82 additions & 0 deletions token-swap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Rarimo sample application: Swapping tokens

This application shows how you can use the Rarimo SDK to swap tokens on the same chain or across chains.
It uses a Vue application for demonstration purposes.

For more information about swaps, see [Swapping tokens](https://docs.rarimo.com/overview/swapping-tokens) in the Rarimo documentation.

## Running the application

To set up this application locally, follow these steps:

1. Make sure that Node.JS and Yarn are installed.

1. Install one of these wallets in your web browser if you don't have one already:

- Coinbase
- Metamask
- NEAR
- Phantom
- Solflare

1. Obtain some UNI tokens as described in the [Instructions for the Rarimo demo application instructions](https://rarimo.gitlab.io/demo-settlement/?path=/story/demo-purchasewithanytoken--demo-instructions&full=true).

1. Clone this folder.

1. In a terminal in this folder, install the dependencies by running this command:

```shell
yarn install
```

1. In the file `src/App.vue`, set the wallet to use by changing the wallet provider from `MetamaskProvider` to your wallet.
For example, to make the application use Coinbase wallets, change `MetamaskProvider` to `CoinbaseProvider`, as in this example:

```vue
<script setup lang="ts">
import { CoinbaseProvider } from '@rarimo/providers-evm'

// ...

const provider = await createProvider(CoinbaseProvider)

// ...

</script>
```

The SDK supports these wallets:
- [`CoinbaseProvider`](https://rarimo.github.io/js-sdk/classes/_rarimo_provider.CoinbaseProvider.html): Coinbase wallets
- [`MetamaskProvider`](https://rarimo.github.io/js-sdk/classes/_rarimo_provider.MetamaskProvider.html): Metamask wallets
- [`NearProvider`](https://rarimo.github.io/js-sdk/classes/_rarimo_provider.NearProvider.html): NEAR wallets
- [`PhantomProvider`](https://rarimo.github.io/js-sdk/classes/_rarimo_provider.PhantomProvider.html): Phantom wallets
- [`SolflareProvider`](https://rarimo.github.io/js-sdk/classes/_rarimo_provider.SolflareProvider.html): Solflare wallets

1. Set the source and destination tokens, chains, and amounts on the following lines.
Make sure that you have enough to make the swap, because token values can vary widely.

```vue
// Source and destination chains and tokens
const sourceChainName = ChainNames.Goerli
const destinationChainName = ChainNames.Fuji

const sourceTokenSymbol = "ETH"
const destinationTokenSymbol = "AVAX"

// Token amounts
const destinationTokenAmount = '1'
```

For information about the chains and tokens that Rarimo supports, see [Swapping tokens](https://docs.rarimo.com/overview/swapping-tokens) in the Rarimo documentation.

1. In the terminal, run `yarn dev` and wait for the application to start and then open the URL `http://localhost:5173` in your web browser.

1. When the application prompts you to connect your wallet, log in to your wallet and allow the connection.

1. On the page, click the Swap button.

If the application is working correctly, it runs the transaction and sends the swapped tokens to your wallet.

## References

This project was created with [Vite](https://vitejs.dev/).
12 changes: 12 additions & 0 deletions token-swap/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
24 changes: 24 additions & 0 deletions token-swap/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "token-swap",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"start": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@rarimo/nft-checkout": "^2.0.0-rc.15",
"@rarimo/provider": "^2.0.0-rc.15",
"@rarimo/providers-evm": "^2.0.0-rc.15",
"@rarimo/shared": "^2.0.0-rc.15",
"ethers": "^5.7.2",
"vue": "^3.3.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.1.0",
"typescript": "^4.9.3",
"vite": "^4.2.0",
"vue-tsc": "^1.2.0"
}
}
108 changes: 108 additions & 0 deletions token-swap/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<template>
<div>
<div>
Source network: {{ sourceChainName }}<br/>
Source token: {{ sourceTokenSymbol }}
</div>
<div style="margin-top:20px">
Destination network: {{ destinationChainName }}<br/>
Destination token: {{ destinationTokenSymbol }}<br/>
Destination token amount: {{ destinationTokenAmount }}
</div>

<button style="margin:46px 0" @click="sendSwapTransaction">Swap</button>

<code>
</code>
</div>
</template>

<script setup lang="ts">
import { ChainNames, BridgeChain } from '@rarimo/shared'
import { CheckoutOperationParams, createCheckoutOperation, EVMOperation, Price } from '@rarimo/nft-checkout'
import { createProvider, ProviderUserRejectedRequest } from '@rarimo/provider'
import { MetamaskProvider } from '@rarimo/providers-evm'
import { ethers } from "ethers"

// Source and destination chains and tokens
const sourceChainName = ChainNames.Goerli
const destinationChainName = ChainNames.Fuji

const sourceTokenSymbol = "ETH"
const destinationTokenSymbol = "AVAX"

// Token amounts
const destinationTokenAmount = '1'

const sendSwapTransaction = async () => {
// Connect to the Metamask wallet in the browser, using the MetamaskProvider interface to limit bundle size.
const provider = await createProvider(MetamaskProvider)

// Initialize the object that represents the transaction operation, in this case on EVM.
const op = createCheckoutOperation(EVMOperation, provider)

// Get the chains that are supported from that chain type.
const chains = await op.getSupportedChains()

// Select the source and destination chains.
// This example uses the Goerli chain, but your application can ask the user which chain to use.
const sourceChain: BridgeChain = chains.find(i => i.name === sourceChainName)!
const destinationChain: BridgeChain = chains.find(i => i.name === destinationChainName)!

// Configure the swap transaction
const swapParams: CheckoutOperationParams = {
// Source and destination chains
chainIdFrom: sourceChain.id,
chainIdTo: destinationChain.id,
// Address to send the swapped tokens to
recipient: provider.address!.toString(),
// Amount of tokens to receive
price: Price.fromRaw(destinationTokenAmount, 18, destinationTokenSymbol),
isMultiplePayment: false,
}

console.log('Swapping',
sourceTokenSymbol, 'on', sourceChainName,
'for', swapParams.price.toString(), destinationTokenSymbol,
'on', destinationChainName
)

// Initialize the transaction
await op.init(swapParams)

// Due to a limitation in the SDK, include an empty bundle for the transaction to work when the transactions are on the same chain.
const bundle = ethers.utils.defaultAbiCoder.encode(
["address[]", "uint256[]","bytes[]"],
[
[],
[],
[],
],
)

// Get the available tokens
const tokens = await op.getPaymentTokens()
if (tokens.length === 0) {
console.log('No tokens in the wallet have a large enough balance to make the swap.')
}

// Make sure that the wallet has enough of the source token
const paymentToken = tokens.find(({ symbol }) => symbol === sourceTokenSymbol)
if (!paymentToken) {
console.log('You do not have enough', sourceTokenSymbol, 'to make the swap.')
}

const estimatedPrices = await op.estimatePrice([paymentToken!])

// Run the transaction.
// The `checkout()` method takes the parameters from the operation instance, gets approval from the user's wallet, and calls the Rarimo contract to handle the transaction.
// Change the next line to await op.checkout(estimatedPrices, { bundle }) if the source and destination chains are the same:
await op.checkout(estimatedPrices)
.then((txHash) => {
console.log('Swap complete:', txHash)
})
.catch((e:ProviderUserRejectedRequest) => {
console.log('The user rejected the transaction.')
})
}
</script>
4 changes: 4 additions & 0 deletions token-swap/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
1 change: 1 addition & 0 deletions token-swap/src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
18 changes: 18 additions & 0 deletions token-swap/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
9 changes: 9 additions & 0 deletions token-swap/tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
7 changes: 7 additions & 0 deletions token-swap/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
})
Loading