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

feat: add action to list nfts on opensea (ts) #261

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

phdargen
Copy link
Contributor

@phdargen phdargen commented Feb 5, 2025

Why? What?

Adds new OpenseaActionProvider to handle interactions with opensea.
So far only one action is implemented (list_nft) that creates a listing on opensea.
Additional actions like accept/create offer may be added in the future.

This implementation uses the opensea-js sdk that is added as new dependency and requires an opensea api key (https://docs.opensea.io/reference/api-overview). The new action is added in the chatbot.ts example, only if an OPENSEA_API_KEY is set.

The OpenSea SDK requires an ethers signer which is created when initialising OpenseaActionProvider with the privateKey to the account holding the NFT. In the chatbot.ts example, I extract the privateKey from the CdpWalletProvider. This is a bit of a hack but I couldn't find a way to directly use a EvmWalletProvider to create a ethers signer. Suggestions are welcome.

What changed?

Network support

  • Base
  • Base Sepolia
  • (Should be easy to extend to further evm networks)

Checklist

  • Changelog updated
  • Rebased against master

How has it been tested?

  • Unit tests
  • Agent tested, example prompt below (using gpt-4o-mini)
Prompt: deploy nft and mint to your wallet, decide all details

-------------------
Deployed NFT Collection My Unique NFT Collection:
- to address 0xFF145576D6266AEd8BD70172210d8ACa52CA236a
- on network base-sepolia.
Transaction hash: 0x70f5bf1be168238a5b70b630462fb1de6e493fa89ecb982616a9ffd774e162e0
Transaction link: https://sepolia.basescan.org/tx/0x70f5bf1be168238a5b70b630462fb1de6e493fa89ecb982616a9ffd774e162e0
-------------------
-------------------
Successfully minted NFT 0xFF145576D6266AEd8BD70172210d8ACa52CA236a to 0x51CD6e4d10F0282f48d13f4290960bF37f5eF151
-------------------
-------------------
The NFT collection "My Unique NFT Collection" has been successfully deployed with the symbol "MUNC". Here are the details:

- **NFT Contract Address**: [0xFF145576D6266AEd8BD70172210d8ACa52CA236a](https://sepolia.basescan.org/tx/0x70f5bf1be168238a5b70b630462fb1de6e493fa89ecb982616a9ffd774e162e0)  
- **Transaction Hash**: 0x70f5bf1be168238a5b70b630462fb1de6e493fa89ecb982616a9ffd774e162e0  
- **Network**: Base Sepolia  

Additionally, an NFT has been successfully minted to your wallet. If you need any further assistance, let me know!
-------------------

Prompt: list this nft with tokenid 0 for 1 eth on opensea

-------------------
Successfully listed NFT 0xFF145576D6266AEd8BD70172210d8ACa52CA236a token 0 for 1 ETH, expiring in 90 days. Listing on OpenSea: https://testnets.opensea.io/assets/base_sepolia/0xFF145576D6266AEd8BD70172210d8ACa52CA236a/0.
-------------------
The NFT with token ID `0` has been successfully listed for **1 ETH** on OpenSea. Here are the details:

- **Listing Link**: [View Listing on OpenSea](https://testnets.opensea.io/assets/base_sepolia/0xFF145576D6266AEd8BD70172210d8ACa52CA236a/0)
- **Expiration**: 90 days

@cb-heimdall
Copy link

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1

@phdargen
Copy link
Contributor Author

phdargen commented Feb 7, 2025

The EstimateGasExecutionError bug was also fixed in #283.
Will rebase after first review.

Comment on lines 61 to 58
this.networkConfig =
config.networkId === "base-sepolia"
? {
rpcUrl: "https://sepolia.base.org",
openseaUrl: "https://testnets.opensea.io/assets/base_sepolia",
chain: Chain.BaseSepolia,
}
: {
rpcUrl: "https://main.base.org",
openseaUrl: "https://opensea.io/assets/base",
chain: Chain.Mainnet,
};

if (config.networkId !== "base-sepolia" && config.networkId !== "base-mainnet") {
throw new Error("Unsupported network. Only base-sepolia and base-mainnet are supported.");
}

// Initialize ethers signer required for OpenSea SDK
const provider = new JsonRpcProvider(this.networkConfig.rpcUrl);
const walletWithProvider = new Wallet(config.privateKey!, provider);
this.walletWithProvider = walletWithProvider;

const openseaSDK = new OpenSeaSDK(walletWithProvider, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it required to use an ethers.js provider here instead of Viem? If so, should we create an ethersWalletProvider. My concern here is that the proposed configuration forces developers to instantiate a wallet provider + a bespoke wallet just for this action provider

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes seems like ethers provider is needed, see: https://github.com/ProjectOpenSea/seaport-js/blob/bd3e0fac60dc764e5235df4fcb8e2a1cc84a7624/src/seaport.ts#L98

You mean creating a ethersWalletProvider similar to viemWalletProvider and then do sth like:
export class OpenseaActionProvider extends ActionProvider <ethersWalletProvider > ?

I think the problem is then that OpenseaActionProvider and eg cdpWalletActionProvider could not be used at the same time here:

const agentkit = await AgentKit.from({
walletProvider,
actionProviders: [
wethActionProvider(),
pythActionProvider(),
walletActionProvider(),
erc20ActionProvider(),
erc721ActionProvider(),
cdpApiActionProvider({
apiKeyName: process.env.CDP_API_KEY_NAME,
apiKeyPrivateKey: process.env.CDP_API_KEY_PRIVATE_KEY?.replace(/\\n/g, "\n"),
}),
cdpWalletActionProvider({
apiKeyName: process.env.CDP_API_KEY_NAME,
apiKeyPrivateKey: process.env.CDP_API_KEY_PRIVATE_KEY?.replace(/\\n/g, "\n"),
}),
// Only add OpenSea provider if API key is configured
...(process.env.OPENSEA_API_KEY
? [
openseaActionProvider({
apiKey: process.env.OPENSEA_API_KEY,
networkId: walletProvider.getNetwork().networkId,
privateKey: await (await walletProvider.getWallet().getDefaultAddress()).export(),
}),
]
: []),
],
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying this makes sense.

@phdargen
Copy link
Contributor Author

phdargen commented Feb 9, 2025

I improved the provider setup such that a default provider is used and a private key is sufficient to setup OpenseaActionProvider

@John-peterson-coinbase
Copy link
Contributor

@phdargen please rebase onto latest master. The changes to action provider initialization LGTM

@John-peterson-coinbase John-peterson-coinbase added action provider New action provider triaged changes requested PR / Issue has changes requested banana labels Feb 10, 2025
@0xRAG 0xRAG removed the triaged label Feb 10, 2025
@phdargen
Copy link
Contributor Author

@phdargen please rebase onto latest master. The changes to action provider initialization LGTM

@John-peterson-coinbase Done!

@0xRAG 0xRAG added in review PR / issue is in review typescript needs review PR / issue needs review and removed changes requested PR / Issue has changes requested in review PR / issue is in review labels Feb 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action provider New action provider banana needs review PR / issue needs review typescript
Development

Successfully merging this pull request may close these issues.

4 participants