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

protocol-kit v2.0 #266

Merged
merged 20 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 14 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
38 changes: 22 additions & 16 deletions safe-core-sdk/api-kit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ yarn add @safe-global/api-kit

## Instantiate an EthAdapter

First of all, we need to create an `EthAdapter`, which contains all the required utilities for the SDKs to interact with the blockchain. It acts as a wrapper for [web3.js](https://web3js.readthedocs.io/) or [ethers.js](https://docs.ethers.io/v5/) Ethereum libraries.
First of all, we need to create an `EthAdapter`, which contains all the required utilities for the SDKs to interact with the blockchain. It acts as a wrapper for [web3.js](https://web3js.readthedocs.io/) or [ethers.js](https://docs.ethers.org/v6/) Ethereum libraries.

Depending on the library used by the Dapp, there are two options:

Expand All @@ -36,7 +36,7 @@ Once the instance of `EthersAdapter` or `Web3Adapter` is created, it can be used
```typescript
import { EthersAdapter } from '@safe-global/protocol-kit'

const provider = new ethers.providers.JsonRpcProvider(config.RPC_URL)
const provider = new ethers.JsonRpcProvider(config.RPC_URL)
const signer = new ethers.Wallet(config.SIGNER_ADDRESS_PRIVATE_KEY, provider)

const ethAdapter = new EthersAdapter({
Expand All @@ -47,47 +47,53 @@ const ethAdapter = new EthersAdapter({

## Initialize the API Kit

We need to create an instance of the API Kit.
We need to create an instance of the API Kit. In those chains where Safe provides a Transaction Service is enough to specify the `chainId`. You can set your own service using the optional `txServiceUrl` parameter.
dasanra marked this conversation as resolved.
Show resolved Hide resolved

```typescript
import SafeApiKit from '@safe-global/api-kit'

const safeApiKit = new SafeApiKit({
txServiceUrl: 'https://safe-transaction-mainnet.safe.global',
ethAdapter
chainId: 1n
})


// or using a custom service
const safeApiKit = new SafeApiKit({
chainId: 1n, // set the correct chainId
txServiceUrl: 'https://url-to-your-custom-service'
})
```

## Propose a transaction to the service

Before a transaction can be executed, any of the Safe signers needs to initiate the process by creating a proposal of a transaction. We send this transaction to the service to make it accessible by the other owners so they can give their approbal and sign the transaction as well.
Before a transaction can be executed, any of the Safe signers needs to initiate the process by creating a proposal of a transaction. We send this transaction to the service to make it accessible by the other owners so they can give their approval and sign the transaction as well.

```typescript
import Safe from '@safe-global/protocol-kit'

// Create Safe instance
const safe = await Safe.create({
const protocolKit = await Safe.create({
ethAdapter,
safeAddress: config.SAFE_ADDRESS
})

// Create transaction
const safeTransactionData: SafeTransactionDataPartial = {
const safeTransactionData: MetaTransactionData = {
to: '0x',
value: '1', // 1 wei
data: '0x',
operation: OperationType.Call
}

const safeTransaction = await safe.createTransaction({ safeTransactionData })
const safeTransaction = await protocolKit.createTransaction({ transactions: [safeTransactionData] })

const senderAddress = await signer.getAddress()
const safeTxHash = await safe.getTransactionHash(safeTransaction)
const signature = await safe.signTransactionHash(safeTxHash)
const safeTxHash = await protocolKit.getTransactionHash(safeTransaction)
const signature = await protocolKit.signTransactionHash(safeTxHash)

// Propose transaction to the service
await safeApiKit.proposeTransaction({
safeAddress: await safe.getAddress(),
safeAddress: await protocolKit.getAddress(),
safeTransactionData: safeTransaction.data,
safeTxHash,
senderAddress,
Expand All @@ -110,14 +116,14 @@ const transaction = await service.getTransaction("<SAFE_TX_HASH>")

## Confirm the transaction

In this step we need to sing the transaction with the Protocol Kit and submit the signature the the Safe Transaction Service using the `confirmTransaction` method.
In this step we need to sign the transaction with the Protocol Kit and submit the signature to the Safe Transaction Service using the `confirmTransaction` method.

```typescript
const safeTxHash = transaction.transactionHash
const signature = await safe.signTransactionHash(safeTxHash)
const signature = await protocolKit.signTransactionHash(safeTxHash)

// Confirm the Safe transaction
const signatureResponse = await service.confirmTransaction(safeTxHash, signature.data)
const signatureResponse = await safeApiKit.confirmTransaction(safeTxHash, signature.data)
```

The Safe transaction is now ready to be executed. This can be done using the Safe{Wallet} web interface, the Protocol Kit or any other tool that is available.
The Safe transaction is now ready to be executed. This can be done using the Safe{Wallet} web interface, the Protocol Kit or any other tool that's available.
38 changes: 38 additions & 0 deletions safe-core-sdk/api-kit/migrating/v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# API Kit: Migrating from v1

This guide aims to be a reference of the major changes between v1 and v2 to help those migrating an existing app.
dasanra marked this conversation as resolved.
Show resolved Hide resolved

## API Kit constructor

Now it won't be necessary to specify a `txServiceUrl` in those environments where Safe has a Transaction Service running, providing the chain ID will be enough. If you want to use your custom service or use the kit in a chain not supported by a Safe Transaction Service, you can add `txServiceUrl` parameter.
dasanra marked this conversation as resolved.
Show resolved Hide resolved

```js
// old:
constructor({ txServiceUrl, ethAdapter }: SafeApiKitConfig)

// new:
constructor({ chainId, txServiceUrl? }: SafeApiKitConfig)
```

## Use the route you prefer

API Kit v1 forced that any custom service was hosted under `/api` route of the URL specified in `txServiceUrl`. This isn't the case anymore, you can specify any route you prefer or subdomain.
dasanra marked this conversation as resolved.
Show resolved Hide resolved

Note that if you use a custom service running under `/api` you will now need to migrate as follow:
dasanra marked this conversation as resolved.
Show resolved Hide resolved

```js
// old:
const txServiceUrl = 'https://your-transaction-service-domain/'
constructor({ txServiceUrl, ethAdapter }: SafeApiKitConfig)

// new:
const txServiceUrl = 'https://your-transaction-service-domain/api'
constructor({ chainId, txServiceUrl? }: SafeApiKitConfig)
```

## MasterCopy to Singleton

To avoid confusion between terms that have been used as synonyms we aligned all our code to use the word `singleton`.
dasanra marked this conversation as resolved.
Show resolved Hide resolved

- Rename type `MasterCopyResponse` to `SafeSingletonResponse`
- Rename method `getServiceMasterCopiesInfo()` to `getServiceSingletonsInfo()`
52 changes: 26 additions & 26 deletions safe-core-sdk/api-kit/reference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,31 @@ yarn add @safe-global/api-kit
Returns the information and configuration of the service.

```typescript
const serviceInfo: SafeServiceInfoResponse = await safeService.getServiceInfo()
const serviceInfo: SafeServiceInfoResponse = await safeApiKit.getServiceInfo()
```

### `getServiceMasterCopiesInfo`
### `getServiceSingletonsInfo`

Returns the list of Safe master copies.
Returns the list of Safe singletons.

```typescript
const masterCopies: MasterCopyResponse = await safeService.getServiceMasterCopiesInfo()
const singletons: SafeSingletonResponse = await safeApiKit.getServiceSingletonsInfo()
```

### `decodeData`

Decodes the specified Safe transaction data.

```typescript
const decodedData = await safeService.decodeData(data)
const decodedData = await safeApiKit.decodeData(data)
```

### `getSafesByOwner`

Returns the list of Safes where the address provided is an owner.

```typescript
const safes: OwnerResponse = await safeService.getSafesByOwner(ownerAddress)
const safes: OwnerResponse = await safeApiKit.getSafesByOwner(ownerAddress)
```

### `getSafesByModule`
Expand All @@ -57,7 +57,7 @@ const safes: ModulesResponse = await getSafesByModule(moduleAddress)
Returns all the information of a Safe transaction.

```typescript
const tx: SafeMultisigTransactionResponse = await safeService.getTransaction(safeTxHash)
const tx: SafeMultisigTransactionResponse = await safeApiKit.getTransaction(safeTxHash)
```

### `getTransactionConfirmations`
Expand All @@ -66,23 +66,23 @@ Returns the list of confirmations for a given a Safe transaction.

```typescript
const confirmations: SafeMultisigConfirmationListResponse =
await safeService.getTransactionConfirmations(safeTxHash)
await safeApiKit.getTransactionConfirmations(safeTxHash)
```

### `confirmTransaction`

Adds a confirmation for a Safe transaction.

```typescript
const signature: SignatureResponse = await safeService.confirmTransaction(safeTxHash, signature)
const signature: SignatureResponse = await safeApiKit.confirmTransaction(safeTxHash, signature)
```

### `getSafeInfo`

Returns the information and configuration of the provided Safe address.

```typescript
const safeInfo: SafeInfoResponse = await safeService.getSafeInfo(safeAddress)
const safeInfo: SafeInfoResponse = await safeApiKit.getSafeInfo(safeAddress)
```

### `getSafeDelegates`
Expand All @@ -98,7 +98,7 @@ const delegateConfig: GetSafeDelegateProps = {
limit, // Optional
offset // Optional
}
const delegates: SafeDelegateListResponse = await safeService.getSafeDelegates(delegateConfig)
const delegates: SafeDelegateListResponse = await safeApiKit.getSafeDelegates(delegateConfig)
```

### `addSafeDelegate`
Expand All @@ -113,7 +113,7 @@ const delegateConfig: AddSafeDelegateProps = {
label,
signer
}
await safeService.addSafeDelegate(delegateConfig)
await safeApiKit.addSafeDelegate(delegateConfig)
```

### `removeSafeDelegate`
Expand All @@ -126,15 +126,15 @@ const delegateConfig: DeleteSafeDelegateProps = {
delegatorAddress,
signer
}
await safeService.removeSafeDelegate(delegateConfig)
await safeApiKit.removeSafeDelegate(delegateConfig)
```

### `getSafeCreationInfo`

Returns the creation information of a Safe.

```typescript
const safeCreationInfo: SafeCreationInfoResponse = await safeService.getSafeCreationInfo(
const safeCreationInfo: SafeCreationInfoResponse = await safeApiKit.getSafeCreationInfo(
safeAddress
)
```
Expand All @@ -145,7 +145,7 @@ Estimates the safeTxGas for a given Safe multi-signature transaction.

```typescript
const estimateTx: SafeMultisigTransactionEstimateResponse =
await safeService.estimateSafeTransaction(safeAddress, safeTransaction)
await safeApiKit.estimateSafeTransaction(safeAddress, safeTransaction)
```

### `proposeTransaction`
Expand All @@ -161,23 +161,23 @@ const transactionConfig: ProposeTransactionProps = {
senderSignature,
origin
}
await safeService.proposeTransaction(transactionConfig)
await safeApiKit.proposeTransaction(transactionConfig)
```

### `getIncomingTransactions`

Returns the history of incoming transactions of a Safe account.

```typescript
const incomingTxs: TransferListResponse = await safeService.getIncomingTransactions(safeAddress)
const incomingTxs: TransferListResponse = await safeApiKit.getIncomingTransactions(safeAddress)
```

### `getModuleTransactions`

Returns the history of module transactions of a Safe account.

```typescript
const moduleTxs: SafeModuleTransactionListResponse = await safeService.getModuleTransactions(
const moduleTxs: SafeModuleTransactionListResponse = await safeApiKit.getModuleTransactions(
safeAddress
)
```
Expand All @@ -187,7 +187,7 @@ const moduleTxs: SafeModuleTransactionListResponse = await safeService.getModule
Returns the history of multi-signature transactions of a Safe account.

```typescript
const multisigTxs: SafeMultisigTransactionListResponse = await safeService.getMultisigTransactions(
const multisigTxs: SafeMultisigTransactionListResponse = await safeApiKit.getMultisigTransactions(
safeAddress
)
```
Expand All @@ -197,13 +197,13 @@ const multisigTxs: SafeMultisigTransactionListResponse = await safeService.getMu
Returns the list of multi-signature transactions that are waiting for the confirmation of the Safe owners.

```typescript
const pendingTxs: SafeMultisigTransactionListResponse = await safeService.getPendingTransactions(
const pendingTxs: SafeMultisigTransactionListResponse = await safeApiKit.getPendingTransactions(
safeAddress
)
```

```typescript
const pendingTxs: SafeMultisigTransactionListResponse = await safeService.getPendingTransactions(
const pendingTxs: SafeMultisigTransactionListResponse = await safeApiKit.getPendingTransactions(
safeAddress,
currentNonce
)
Expand All @@ -214,7 +214,7 @@ const pendingTxs: SafeMultisigTransactionListResponse = await safeService.getPen
Returns a list of transactions for a Safe. The list has different structures depending on the transaction type.

```typescript
const allTxs: SafeMultisigTransactionListResponse = await safeService.getAllTransactions(
const allTxs: SafeMultisigTransactionListResponse = await safeApiKit.getAllTransactions(
safeAddress
)
```
Expand All @@ -225,7 +225,7 @@ const allTxsOptions: AllTransactionsOptions = {
queued,
trusted
}
const allTxs: SafeMultisigTransactionListResponse = await safeService.getAllTransactions(
const allTxs: SafeMultisigTransactionListResponse = await safeApiKit.getAllTransactions(
safeAddress,
allTxsOptions
)
Expand All @@ -236,21 +236,21 @@ const allTxs: SafeMultisigTransactionListResponse = await safeService.getAllTran
Returns the right nonce to propose a new transaction right after the last pending transaction.

```typescript
const nextNonce = await safeService.getNextNonce(safeAddress)
const nextNonce = await safeApiKit.getNextNonce(safeAddress)
```

### `getTokenList`

Returns the list of all the ERC20 tokens handled by the Safe.

```typescript
const tokens: TokenInfoListResponse = await safeService.getTokenList()
const tokens: TokenInfoListResponse = await safeApiKit.getTokenList()
```

### `getToken`

Returns the information of a given ERC20 token.

```typescript
const token: TokenInfoResponse = await safeService.getToken(tokenAddress)
const token: TokenInfoResponse = await safeApiKit.getToken(tokenAddress)
```
8 changes: 4 additions & 4 deletions safe-core-sdk/auth-kit/guides/web3auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ Once connected, you can use any of the methods available in the [Protocol Kit](h
import { ethers } from 'ethers'
import { EthersAdapter } from '@safe-global/protocol-kit'

provider = new ethers.providers.Web3Provider(web3AuthModalPack.getProvider())
provider = new ethers.BrowserProvider(web3AuthModalPack.getProvider())
signer = provider.getSigner()

const ethAdapter = new EthersAdapter({
Expand All @@ -162,10 +162,10 @@ const safeSDK = await Safe.create({
const safeTransactionData: MetaTransactionData = {
to: '0x',
data: '0x',
value: ethers.utils.parseUnits('0.0001', 'ether').toString()
value: ethers.parseUnits('0.0001', 'ether').toString()
}

const safeTransaction = await safeSDK.createTransaction({ safeTransactionData })
const safeTransaction = await safeSDK.createTransaction({ transactions: [safeTransactionData] })
```

## Sign messages using the `Web3AuthModalPack`
Expand All @@ -183,7 +183,7 @@ const address = '0x...'
await web3.eth.personal.sign(message, address)

// Using ethers
const provider = new ethers.providers.Web3Provider(web3AuthModalPack.getProvider())
const provider = new ethers.BrowserProvider(web3AuthModalPack.getProvider())
const signer = provider.getSigner()

await signer.sendTransaction(tx)
Expand Down
Loading
Loading