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

PRO-2196 - Added ARKA wrapper as sub package #110

Merged
merged 3 commits into from
Mar 20, 2024
Merged
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Changelog
## [1.6.3] - 2024-03-19
### New
- Added ArkaPaymaster as a sub-module

## [1.6.2] - 2024-03-15
### Bug Fixes
- Fixed browser-side querystring issue
Expand Down
23 changes: 23 additions & 0 deletions examples/24-ArkaPaymaster.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ArkaPaymaster } from "../src";
import * as dotenv from 'dotenv';

dotenv.config();

async function main() {
const arka_api_key = 'arka_public_key';
const arka_url = 'https://arka.etherspot.io'; // Only testnets are available, if you need further assistance in setting up a paymaster service for your dapp, please reach out to us on discord or https://etherspot.fyi/arka/intro

// initializating sdk...
const arkaPaymaster = new ArkaPaymaster(Number(process.env.CHAIN_ID), arka_api_key, arka_url);

console.log(await arkaPaymaster.metadata());
console.log(await arkaPaymaster.getTokenPaymasterAddress("eUSDC"))
console.log(await arkaPaymaster.addWhitelist(["0xB3aF6CFDDc444B948132753AD8214a20605692eF"]));
console.log(await arkaPaymaster.removeWhitelist(["0xB3aF6CFDDc444B948132753AD8214a20605692eF"]));
console.log(await arkaPaymaster.checkWhitelist("0xB3aF6CFDDc444B948132753AD8214a20605692eF"));
console.log(await arkaPaymaster.deposit(0.001));
}

main()
.catch(console.error)
.finally(() => process.exit());
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@etherspot/prime-sdk",
"version": "1.6.2",
"version": "1.6.3",
"description": "Etherspot Prime (Account Abstraction) SDK",
"keywords": [
"ether",
Expand Down
3 changes: 2 additions & 1 deletion src/sdk/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DataUtils } from './dataUtils';
import { PrimeSdk } from './sdk';
import { ArkaPaymaster } from './paymaster';

export * from './api';
export * from './dto';
Expand All @@ -9,5 +10,5 @@ export * from './state';
export * from './wallet';
export * from './bundler';

export { PrimeSdk, DataUtils };
export { PrimeSdk, DataUtils, ArkaPaymaster };
export default PrimeSdk;
1 change: 0 additions & 1 deletion src/sdk/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export interface SdkOptions {
stateStorage?: StateStorage;
rpcProviderUrl?: string;
graphqlEndpoint?: string;
etherspotBundlerApiKey?: string;
factoryWallet?: Factory;
walletFactoryAddress?: string;
entryPointAddress?: string;
Expand Down
5 changes: 5 additions & 0 deletions src/sdk/paymaster/ErrorMsg.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const ErrorMessage = {
INVALID_ADDRESSES: 'Address Invalid. Please make sure that all the addresses are valid',
INVALID_ADDRESS: 'The given address is invalid. Please try again with valid address',
MAX_ADDRESSES: 'Max of 10 addresses are only allowed in one request',
}
2 changes: 2 additions & 0 deletions src/sdk/paymaster/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './interface';
export * from './provider';
6 changes: 6 additions & 0 deletions src/sdk/paymaster/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

export interface PaymasterProvider {
readonly url: string;
}

export type PaymasterProviderLike = PaymasterProvider;
210 changes: 210 additions & 0 deletions src/sdk/paymaster/provider/arka.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { ethers } from "ethers";
import { PaymasterProvider } from "../interface";
import { ErrorMessage } from "../ErrorMsg";

export class ArkaPaymaster implements PaymasterProvider {
readonly url: string;
readonly apiKey: string;
readonly chainId: number;
readonly queryParams: string;

constructor(chainId: number, apiKey: string, paymasterUrl: string) {
this.url = paymasterUrl;
this.queryParams = `?apiKey=${apiKey}&chainId=${chainId}`;
this.apiKey = apiKey;
this.chainId = chainId;
}

/* This method is to get the paymaster address for the given token symbol if available
* @param tokenSym, the token symbol used as string ex: "USDC"
*/
async getTokenPaymasterAddress(tokenSym: string) {
vignesha22 marked this conversation as resolved.
Show resolved Hide resolved
let response = null;
const entryPointAddressV06 = '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789';
const context = { token: tokenSym }
try {
response = await fetch(`${this.url}/pimlicoAddress${this.queryParams}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ params: [entryPointAddressV06, context] }),
})
.then(async (res) => {
const responseJson = await res.json();
if (responseJson.error) {
throw new Error(responseJson.error);
}
return responseJson
})
.catch((err) => {
throw new Error(err.message);
})
} catch (err) {
throw new Error(err.message)
}
if (response.message) return response.message;
return response;
}

/* This method is to whitelist the addresses given
* @param addresses, the array of addresses that needs to be whitelisted
*/
async addWhitelist(addresses: string[]) {
let response = null;
if (addresses.length > 10) throw new Error(ErrorMessage.MAX_ADDRESSES);
const validAddresses = addresses.every(ethers.utils.isAddress);
if (!validAddresses) throw new Error(ErrorMessage.INVALID_ADDRESS);
try {
response = await fetch(`${this.url}/whitelist${this.queryParams}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ params: [addresses] }),
})
.then(async (res) => {
const responseJson = await res.json();
if (responseJson.error) {
throw new Error(responseJson.error);
}
return responseJson
})
.catch((err) => {
throw new Error(err.message);
})
} catch (err) {
throw new Error(err.message)
}
if (response.message) return response.message;
return response;
}

/* This method is to remove whitelisted addresses given
* @param addresses, the array of addresses that needs to be removed from whitelist
*/
async removeWhitelist(addresses: string[]) {
let response = null;
if (addresses.length > 10) throw new Error(ErrorMessage.MAX_ADDRESSES);
const validAddresses = addresses.every(ethers.utils.isAddress);
if (!validAddresses) throw new Error(ErrorMessage.INVALID_ADDRESS);
try {
response = await fetch(`${this.url}/removeWhitelist${this.queryParams}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ params: [addresses] }),
})
.then(async (res) => {
const responseJson = await res.json();
if (responseJson.error) {
throw new Error(responseJson.error);
}
return responseJson
})
.catch((err) => {
throw new Error(err.message);
})
} catch (err) {
throw new Error(err.message)
}
if (response.message) return response.message;
return response;
}

/* This method is to check a given address is whitelisted or not
* @param address, address that needs to be checked if its whitelisted or not
*/
async checkWhitelist(address: string) {
let response = null;
if (!ethers.utils.isAddress(address)) throw new Error(ErrorMessage.INVALID_ADDRESS)
try {
response = await fetch(`${this.url}/checkWhitelist${this.queryParams}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ params: [address] }),
})
.then(async (res) => {
const responseJson = await res.json();
if (responseJson.error) {
throw new Error(responseJson.error);
}
return responseJson
})
.catch((err) => {
throw new Error(err.message);
})
} catch (err) {
throw new Error(err.message)
}
if (response.message) return response.message;
return response;
}

/* This method is to deposit the amount for the paymaster to the entryPoint contract
* @param amountInEth, amount that needs to be deposited in ETH terms
*/
async deposit(amountInEth: number) {
let response = null;
try {
response = await fetch(`${this.url}/deposit${this.queryParams}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ params: [amountInEth] }),
})
.then(async (res) => {
const responseJson = await res.json();
if (responseJson.error) {
throw new Error(responseJson.error);
}
return responseJson
})
.catch((err) => {
throw new Error(err.message);
})
} catch (err) {
throw new Error(err.message)
}
if (response.message) return response.message;
return response;
}

// This method is to get the details of the paymaster associated to your apiKey
async metadata() {
let response = null;
try {
response = await fetch(`${this.url}/metadata${this.queryParams}`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
})
.then(async (res) => {
const responseJson = await res.json();
if (responseJson.error) {
throw new Error(responseJson.error);
}
return responseJson
})
.catch((err) => {
throw new Error(err.message);
})
} catch (err) {
throw new Error(err.message)
}
if (response.message) return response.message;
return response;
}

}
1 change: 1 addition & 0 deletions src/sdk/paymaster/provider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './arka';
Loading