Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

chore: update relayer docs to v5 #492

Merged
merged 1 commit into from
Jun 28, 2024
Merged
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
234 changes: 140 additions & 94 deletions src/app/engine/features/relayers/page.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Callout, DocImage } from "@doc";
import { Details, Callout, DocImage } from "@doc";
import Relayer1 from "../../assets/relayer-1.png";
import { createMetadata } from "@doc";

Expand All @@ -10,19 +10,35 @@ export const metadata = createMetadata({

# Relayers

Use Engine as a relayer to submit meta-transactions on behalf of your users. Relayers allow your users to send blockchain transactions and have [gas fees](/glossary/gas) paid by your backend wallets.
Use Engine as a relayer to sponsor gas for transactions on behalf of your users. Users sign a transaction with their own wallet (no gas required), and pay [gas fees](/glossary/gas) with an Engine backend wallet.

For example, your users can transfer or list NFTs in their wallet without having gas funds.
Removing the need for your users to get gas greatly improves the user experience and reach of your dApp.

[Learn more about gasless transactions.](/glossary/gasless-transactions)
## Use cases

Enable users to claim, transfer, list, or burn NFTs with no gas. [Learn more about gasless transactions.](/glossary/gasless-transactions)

## Requirements

- The contract you are calling must support a standard meta-transaction format:
- [EIP-2771 Native Meta-transactions](https://eips.ethereum.org/EIPS/eip-2771)
- [EIP-2612 Permit Approval](https://eips.ethereum.org/EIPS/eip-2612)
- [Polygon Native Meta-transactions](https://wiki.polygon.technology/docs/pos/design/transactions/meta-transactions/meta-transactions/)
- Your Engine instance has a [backend wallet](/engine/features/backend-wallets) with funds.
- The target contract must support one of:
- [EIP-2771 meta transactions](https://eips.ethereum.org/EIPS/eip-2771) \*
- [EIP-2612 permit approval](https://eips.ethereum.org/EIPS/eip-2612)
- [Polygon meta transactions](https://docs.polygon.technology/pos/concepts/transactions/meta-transactions/)

\*The target contract must trust a forwarder that implements the `verify` and `execute` methods, like thirdweb's default forwarder (0xd04f98c88ce1054c90022ee34d566b9237a1203c).

## Allow calls to Engine from your domain (CORS)

1. Navigate to the **Configuration** section in the [Engine dashboard](https://thirdweb.com/dashboard/engine).
1. Under **Allowlisted Domains**, enter your application domain(s).
- Include local or development environments for testing.

<Callout variant='warning' title="The relay endpoint is unauthenticated.">

Set **Allowed Contracts** and **Allowed Forwarders** to restrict transactions your relayer allows.

</Callout>

## Create a relayer

Expand All @@ -35,106 +51,136 @@ For example, your users can transfer or list NFTs in their wallet without having
- **Allowed Contracts**: (Optional) A list of contract addresses this relayer is allowed to submit transactions to.
- **Allowed Forwarders**: (Optional) A list of forwarder addresses this relayer is allowed to submit transactions to.

The relayer will be assigned an ID.
The relayer URL to submit transactions to will look like this: `https://<your_engine_url>/relayer/<relayer_id>`

## Submit to a relayer from your app frontend

First, update the CORS policy on Engine to allow your webapp to call Engine.
The relayer will be assigned a URL in this format: `https://<engine_url>/relayer/<relayer_id>`

- URL: `POST /configuration/cors`
- Header
- `Authorization: Bearer <access_token>`
- `Content-Type: application/json`
- Body (example)
```json
{
"urlsToAdd": [
"http://localhost:8000",
"https://dev.my-app.com",
"https://my-app.com"
]
}
```
## Submit a meta transaction from your app frontend

<Callout variant='info' title="Security note">
Use the [Connect SDK](/react) to prompt the user to sign transactions and send it this relayer.

Relayer endpoints can be called by frontend clients without authentication. Set **Allowed Contracts** and **Allowed Forwarders** to restrict the meta-transactions your relayer will handle.
First wrap your app with `<ThirdwebProvider>`:

All other Engine endpoints are authenticated by access token.

</Callout>
```tsx
import { ThirdwebProvider } from "thirdweb/react";

Next, use the [thirdweb React SDK](/react) to allow users to sign transactions with their wallet and send it to your Engine relayer.
<ThirdwebProvider>
<YourApp />
</ThirdwebProvider>;
```

Pass the relayer URL to the SDK provider.
Next prompt the user to connect a wallet. See [ConnectButton](https://portal.thirdweb.com/connect/sign-in/ConnectButton) for customization options.

```tsx
import { ThirdwebProvider } from "@thirdweb-dev/react";

export default function App() {
return (
<ThirdwebProvider
activeChain="polygon"
sdkOptions={{
gasless: {
engine: {
relayerUrl: <engine_relayer_url>,
},
},
}}
>
<ConnectWallet/>
<MintComponent />
</ThirdwebProvider>
);
}
```
import { ConnectButton } from "thirdweb/react";

Enable users to connect their wallet with the [`ConnectButton`](/typescript/v5/react/components/ConnectButton) component.
<ConnectButton client={client} />;
```

```tsx
import { ConnectWallet } from "@thirdweb-dev/react";
This example will call the `claim` method on an [NFT Drop contract](https://portal.thirdweb.com/contracts/explore/pre-built-contracts/nft-drop):

export function Connect() {
return <ConnectWallet />;
}
```solidity
function claim(address _receiver, uint256 _quantity, address _currency, uint256 _pricePerToken, AllowlistProof calldata _allowlistProof, bytes memory _data)
```

Create a button that sends a blockchain transaction.
Render a `<TransactionButton>` to prepare a transaction to be relayed via Engine.

```tsx
import { useContract } from "@thirdweb-dev/react";

export default function MintComponent() {
const contract = useContract("0x7A0CE8524bea337f0beE853B68fAbDE145dAC0A0");

return (
<Button
onClick={() => {
// This mint transaction will be submitted by your Engine relayer.
await contract.erc20.mint(1);
}}
>
Claim
</Button>
);
}
import { TransactionButton } from "thirdweb/react";

<TransactionButton
transaction={() => {
const contract = getContract({
client,
chain,
address: NFT_ADDRESS,
});

return prepareContractCall({
contract,
method: resolveMethod("claim"),
params: [
// receiver
account.address,
// quantity
1n,
// currency
NATIVE_TOKEN_ADDRESS,
// pricePerToken
0n,
// allowlistProof
{
proof: [],
quantityLimitPerWallet: 0n,
pricePerToken: 0n,
currency: NATIVE_TOKEN_ADDRESS,
},
// data
"0x",
],
});
}}
onTransactionSent={(result) =>
console.log("Submitted:", result.transactionHash)
}
onTransactionConfirmed={(receipt) =>
console.log("Confirmed:", receipt.transactionHash)
}
onError={(error) => console.error("Error:", error)}
gasless={{
provider: "engine",
relayerUrl: RELAYER_URL, // e.g. https://<engine_url>/relayer/<relayer_id>
relayerForwarderAddress: FORWARDER_ADDRESS, // a trusted forwarder on the contract
}}
>
Claim
</TransactionButton>;
```

## Submit to a relayer from your app backend

Alternatively, submit transactions to your Engine relayer from your app backend.

1. Prompt the user to _sign_ a transaction, such as transferring an NFT or minting a token.
- This step does not require gas in the user's wallet.
- Ensure the signature matches the format that the forwarder expects.
1. Pass the signature from your app frontend to your app backend.
1. Call Engine from your app backend.
- Method: `POST https://<engine_url>/relayer/{relayer_id}`
- Body:
- `type`: "forward", "permit", or "execute-meta-transaction"
- `request`: The transaction request details
- `signature`: The `request` signed by the user's wallet
- `forwarderAddress`: A forwarder address that is trusted by the contract, if `type` = "forward"
- See the [API reference](https://redocly.github.io/redoc/?url=https://demo.web3api.thirdweb.com/json#tag/Relayer/operation/relay) for details.
## Submit a meta transaction from your app backend (Advanced)

Alternatively submit transactions to your relayer from your backend. This approach allows you to apply server-side validation or business logic before submitting the transaction to be relayed.

1. Prompt the user to sign a transaction.
- This step does not require gas.
- The signature must match the format that the forwarder expects.
1. Call your backend with this signature.
1. Call Engine from your backend: `POST https://<engine_url>/relayer/{relayer_id}`

<Details id="relayer-body-payload" summary="Body payload">

```typescript
{
type: "forward";
request: {
chainid?: string | undefined;
from: string;
to: string;
value: string;
gas: string;
nonce: string;
data: string;
};
signature: string;
forwarderAddress: string;
} | {
type: "permit";
request: {
to: string;
owner: string;
spender: string;
value: string;
nonce: string;
deadline: string;
};
signature: string;
} | {
type: "execute-meta-transaction";
request: {
from: string;
to: string;
data: string;
};
signature: string;
}
```

</Details>
Loading