Skip to content

Commit

Permalink
feat: add buy nft
Browse files Browse the repository at this point in the history
  • Loading branch information
mishuagopian committed Feb 13, 2025
1 parent c080f0e commit 483fcac
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
},
"dependencies": {
"@apollo/client": "~3.9.10",
"@reservoir0x/reservoir-sdk": "^2.5.6",
"abitype": "^1.0.0",
"apollo-link-scalars": "^4.0.2",
"ethers": "^6.0.8",
Expand Down
62 changes: 62 additions & 0 deletions src/gondi.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import {
createClient,
Execute,
reservoirChains,
ReservoirClient,
} from '@reservoir0x/reservoir-sdk';
import {
Account,
Address,
Expand All @@ -12,6 +18,7 @@ import { Api, Props as ApiProps } from '@/api';
import { Auction, zeroAddress, zeroHash, zeroHex } from '@/blockchain';
import { Contracts, GondiPublicClient, Wallet } from '@/contracts';
import {
Currency,
MarketplaceEnum,
OffersSortField,
Ordering,
Expand All @@ -30,6 +37,7 @@ import {
} from '@/utils/loan';
import { min } from '@/utils/number';
import { FULFILLED, REJECTED } from '@/utils/promises';
import { isCurrencyApproval, sendTransaction, validateSteps } from '@/utils/reservoir';
import { areSameAddress } from '@/utils/string';
import { OptionalNullable } from '@/utils/types';

Expand All @@ -40,6 +48,7 @@ export class Gondi {
bcClient: GondiPublicClient;
api: Api;
defaults: { Msl: Address; UserVault: Address };
reservoirClient: ReservoirClient;

constructor({ wallet, apiClient }: GondiProps) {
this.wallet = wallet;
Expand All @@ -54,6 +63,16 @@ export class Gondi {
UserVault: this.contracts.UserVaultV6.address,
};
this.api = new Api({ wallet, apiClient });
this.reservoirClient = createClient({
chains: [
{
id: wallet.chain.id,
name: wallet.chain.name,
baseApiUrl: reservoirChains.mainnet.baseApiUrl,
active: true,
},
],
});
}

async makeSingleNftOffer(offer: model.SingleNftOfferInput) {
Expand Down Expand Up @@ -969,6 +988,49 @@ export class Gondi {
price,
});
}

async buyNft({
price,
currency,
orderId,
}: {
price: bigint;
currency: Pick<Currency, 'address' | 'decimals'>;
orderId: string;
}) {
const buyResult = await this.reservoirClient.actions.buyToken({
items: [{ orderId }],
wallet: this.wallet,
expectedPrice: {
[currency.address]: {
raw: price,
currencyAddress: currency.address,
currencyDecimals: currency.decimals,
},
},
onProgress: (_steps: Execute['steps']) => void 0,
options: {
currency: currency.address,
excludeEOA: true,
skipBalanceCheck: true,
},
precheck: true,
});

if (buyResult === true) throw new Error('Steps were expected');

const { steps } = buyResult;
validateSteps(steps);

for (const step of steps) {
if (isCurrencyApproval(step)) {
// TODO: check if approval already set for currency
await sendTransaction(this.wallet, this.bcClient, step);
} else {
await sendTransaction(this.wallet, this.bcClient, step);
}
}
}
}

interface GondiProps {
Expand Down
37 changes: 37 additions & 0 deletions src/utils/reservoir.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Execute } from '@reservoir0x/reservoir-sdk';

import { GondiPublicClient, Wallet } from '@/contracts';

type TransactionStep = Execute['steps'][number];
type MinimalStep = Pick<TransactionStep, 'kind' | 'id' | 'items'>;

const isTransaction = (step: MinimalStep) => step.kind === 'transaction';

const isSale = (step: MinimalStep) =>
step.id === 'sale' && isTransaction(step) && step.items?.length === 1;

export const isCurrencyApproval = (step: MinimalStep) =>
step.id === 'currency-approval' && isTransaction(step) && step.items?.length === 1;

export const validateSteps = (steps: MinimalStep[]) => {
for (const step of steps) {
if (!isCurrencyApproval(step) && !isSale(step)) {
throw new Error(`Unknown step: ${step.id} - ${step.kind}: ${step}`);
}
}
};

export const sendTransaction = async (
wallet: Wallet,
bcClient: GondiPublicClient,
step: TransactionStep,
) => {
const txHash = await wallet.sendTransaction(step.items?.[0].data);
const receipt = await bcClient.waitForTransactionReceipt({
hash: txHash,
});
if (receipt.status !== 'success') {
throw new Error(`Transaction failed: ${txHash}`);
}
return receipt;
};
90 changes: 90 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2693,6 +2693,17 @@ __metadata:
languageName: node
linkType: hard

"@reservoir0x/reservoir-sdk@npm:^2.5.6":
version: 2.5.6
resolution: "@reservoir0x/reservoir-sdk@npm:2.5.6"
dependencies:
axios: "npm:^1.6.7"
peerDependencies:
viem: ~2.22.8
checksum: 10/5f2d95f05189c891758ef31e8a3917e08d766691ec88afd9ab35f743fc165ede0847a15ab55814cc57b1bb75f30b4435248a4e895ed76c5d9be86900b20176c5
languageName: node
linkType: hard

"@scure/base@npm:~1.1.7":
version: 1.1.9
resolution: "@scure/base@npm:1.1.9"
Expand Down Expand Up @@ -3502,6 +3513,13 @@ __metadata:
languageName: node
linkType: hard

"asynckit@npm:^0.4.0":
version: 0.4.0
resolution: "asynckit@npm:0.4.0"
checksum: 10/3ce727cbc78f69d6a4722517a58ee926c8c21083633b1d3fdf66fd688f6c127a53a592141bd4866f9b63240a86e9d8e974b13919450bd17fa33c2d22c4558ad8
languageName: node
linkType: hard

"auto-bind@npm:~4.0.0":
version: 4.0.0
resolution: "auto-bind@npm:4.0.0"
Expand All @@ -3518,6 +3536,17 @@ __metadata:
languageName: node
linkType: hard

"axios@npm:^1.6.7":
version: 1.7.9
resolution: "axios@npm:1.7.9"
dependencies:
follow-redirects: "npm:^1.15.6"
form-data: "npm:^4.0.0"
proxy-from-env: "npm:^1.1.0"
checksum: 10/b7a5f660ea53ba9c2a745bf5ad77ad8bf4f1338e13ccc3f9f09f810267d6c638c03dac88b55dae8dc98b79c57d2d6835be651d58d2af97c174f43d289a9fd007
languageName: node
linkType: hard

"babel-jest@npm:^29.7.0":
version: 29.7.0
resolution: "babel-jest@npm:29.7.0"
Expand Down Expand Up @@ -4162,6 +4191,15 @@ __metadata:
languageName: node
linkType: hard

"combined-stream@npm:^1.0.8":
version: 1.0.8
resolution: "combined-stream@npm:1.0.8"
dependencies:
delayed-stream: "npm:~1.0.0"
checksum: 10/2e969e637d05d09fa50b02d74c83a1186f6914aae89e6653b62595cc75a221464f884f55f231b8f4df7a49537fba60bdc0427acd2bf324c09a1dbb84837e36e4
languageName: node
linkType: hard

"commander@npm:^9.0.0":
version: 9.5.0
resolution: "commander@npm:9.5.0"
Expand Down Expand Up @@ -4421,6 +4459,13 @@ __metadata:
languageName: node
linkType: hard

"delayed-stream@npm:~1.0.0":
version: 1.0.0
resolution: "delayed-stream@npm:1.0.0"
checksum: 10/46fe6e83e2cb1d85ba50bd52803c68be9bd953282fa7096f51fc29edd5d67ff84ff753c51966061e5ba7cb5e47ef6d36a91924eddb7f3f3483b1c560f77a0020
languageName: node
linkType: hard

"dependency-graph@npm:^0.11.0":
version: 0.11.0
resolution: "dependency-graph@npm:0.11.0"
Expand Down Expand Up @@ -5466,6 +5511,16 @@ __metadata:
languageName: node
linkType: hard

"follow-redirects@npm:^1.15.6":
version: 1.15.9
resolution: "follow-redirects@npm:1.15.9"
peerDependenciesMeta:
debug:
optional: true
checksum: 10/e3ab42d1097e90d28b913903841e6779eb969b62a64706a3eb983e894a5db000fbd89296f45f08885a0e54cd558ef62e81be1165da9be25a6c44920da10f424c
languageName: node
linkType: hard

"for-each@npm:^0.3.3":
version: 0.3.3
resolution: "for-each@npm:0.3.3"
Expand All @@ -5485,6 +5540,17 @@ __metadata:
languageName: node
linkType: hard

"form-data@npm:^4.0.0":
version: 4.0.1
resolution: "form-data@npm:4.0.1"
dependencies:
asynckit: "npm:^0.4.0"
combined-stream: "npm:^1.0.8"
mime-types: "npm:^2.1.12"
checksum: 10/6adb1cff557328bc6eb8a68da205f9ae44ab0e88d4d9237aaf91eed591ffc64f77411efb9016af7d87f23d0a038c45a788aa1c6634e51175c4efa36c2bc53774
languageName: node
linkType: hard

"fs-minipass@npm:^2.0.0":
version: 2.1.0
resolution: "fs-minipass@npm:2.1.0"
Expand Down Expand Up @@ -5730,6 +5796,7 @@ __metadata:
"@graphql-codegen/typescript-apollo-client-helpers": "npm:^2.2.6"
"@graphql-codegen/typescript-generic-sdk": "npm:^3.1.0"
"@graphql-codegen/typescript-operations": "npm:^3.0.4"
"@reservoir0x/reservoir-sdk": "npm:^2.5.6"
"@types/node": "npm:^20.4.6"
"@typescript-eslint/eslint-plugin": "npm:^5.49.0"
"@typescript-eslint/parser": "npm:^5.49.0"
Expand Down Expand Up @@ -7571,6 +7638,22 @@ __metadata:
languageName: node
linkType: hard

"mime-db@npm:1.52.0":
version: 1.52.0
resolution: "mime-db@npm:1.52.0"
checksum: 10/54bb60bf39e6f8689f6622784e668a3d7f8bed6b0d886f5c3c446cb3284be28b30bf707ed05d0fe44a036f8469976b2629bbea182684977b084de9da274694d7
languageName: node
linkType: hard

"mime-types@npm:^2.1.12":
version: 2.1.35
resolution: "mime-types@npm:2.1.35"
dependencies:
mime-db: "npm:1.52.0"
checksum: 10/89aa9651b67644035de2784a6e665fc685d79aba61857e02b9c8758da874a754aed4a9aced9265f5ed1171fd934331e5516b84a7f0218031b6fa0270eca1e51a
languageName: node
linkType: hard

"mimic-fn@npm:^2.1.0":
version: 2.1.0
resolution: "mimic-fn@npm:2.1.0"
Expand Down Expand Up @@ -8448,6 +8531,13 @@ __metadata:
languageName: node
linkType: hard

"proxy-from-env@npm:^1.1.0":
version: 1.1.0
resolution: "proxy-from-env@npm:1.1.0"
checksum: 10/f0bb4a87cfd18f77bc2fba23ae49c3b378fb35143af16cc478171c623eebe181678f09439707ad80081d340d1593cd54a33a0113f3ccb3f4bc9451488780ee23
languageName: node
linkType: hard

"punycode@npm:^1.3.2":
version: 1.4.1
resolution: "punycode@npm:1.4.1"
Expand Down

0 comments on commit 483fcac

Please sign in to comment.