Skip to content

Commit

Permalink
Merge pull request #38 from 4-point-0/rimatik/near-provider-buy-for-user
Browse files Browse the repository at this point in the history
added nearProviderService with buy_for_user method
  • Loading branch information
rimatik authored Dec 20, 2023
2 parents 64fe53a + df853df commit 5c360ce
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 1 deletion.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@types/uuid": "^9.0.2",
"aws-sdk": "^2.1413.0",
"axios": "^1.4.0",
"bn.js": "^5.2.1",
"borsh": "^0.7.0",
"cache-manager": "^5.2.3",
"class-transformer": "^0.5.1",
Expand All @@ -65,6 +66,7 @@
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
"@types/bn.js": "^5.1.5",
"@types/cron": "^2.0.1",
"@types/express": "^4.17.13",
"@types/jest": "29.2.4",
Expand Down
6 changes: 6 additions & 0 deletions src/common/config/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,10 @@ export const configuration = () => ({
},
email_domains: process.env.EMAIL_DOMAINS,
storage_cost_usd: process.env.STORAGE_COST_USD,
near: {
network_id: process.env.NEAR_NETWORK_ID,
nft_contract_account_id: process.env.NEAR_NFT_CONTRACT_ACCOUNT_ID,
master_account_id: process.env.NEAR_MASTER_ACCOUNT_ID,
master_account_private_key: process.env.NEAR_MASTER_ACCOUNT_PRIVATE_KEY,
},
});
120 changes: 120 additions & 0 deletions src/modules/near-provider/near-provider.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { BN } from 'bn.js';
import * as nearAPI from 'near-api-js';

/* It's a service that connects to the NEAR blockchain and provides methods for interacting with the NFT contract */
@Injectable()
export class NearProviderService {
private readonly logger = new Logger(NearProviderService.name);

// NEAR network ID (e.g. localnet, betanet, testnet, mainnet). For us it's testnet or mainnet
private networkId: string;

// NEAR account ID of the contract that will have NFTs
private nftContractAccountId: string;

// NEAR account ID of the account that will pay to mint NFTs
private masterAccountId: string;

// NEAR account private key of the account that will pay to mint NFTs
private masterAccountPrivateKey: string;

// NEAR config
private config: nearAPI.ConnectConfig;

// NEAR instance
private near: nearAPI.Near | null;

// NEAR account instance of the master account that will call contract to mint NFTs
private masterAccount: nearAPI.Account | null;

// NEAR key store
private keyStore = new nearAPI.keyStores.InMemoryKeyStore();

// Boatload of gas to pay for minting/burning NFTs (300 Tgas). We don't care about this gas because NEAR will refund unused gas
private gas = new BN('300000000000000');

/**
* We're creating a constructor function that takes in a configService object as a parameter using dependecy injection. We're
* then setting the networkId, nftContractAccountId, masterAccountId, and masterAccountPrivateKey to
* the values that we get from the configService object
* @param {ConfigService} configService - This is a service that we'll use to get the configuration
* values from the .env file.
*/
constructor(private readonly configService: ConfigService) {
this.networkId = this.configService.get('near.network_id');
this.nftContractAccountId = this.configService.get(
'near.nft_contract_account_id',
);
this.masterAccountId = this.configService.get('near.master_account_id');
this.masterAccountPrivateKey = this.configService.get(
'near.master_account_private_key',
);

this.near = null;
this.masterAccount = null;
}

async onModuleInit() {
await this.init();
}

/**
* It connects to the NEAR blockchain and sets up the master account
*/
private async init() {
if (this.near && this.masterAccount) return;

this.config = {
networkId: this.networkId,
nodeUrl: `https://rpc.${this.networkId}.near.org`,
walletUrl: `https://wallet.${this.networkId}.near.org`,
helperUrl: `https://helper.${this.networkId}.near.org`,
};

const masterAccountKeyPair = nearAPI.KeyPair.fromString(
this.masterAccountPrivateKey,
);

await this.keyStore.setKey(
this.config.networkId,
this.masterAccountId,
masterAccountKeyPair,
);

this.near = await nearAPI.connect({
...this.config,
keyStore: this.keyStore,
});

this.masterAccount = await this.near.account(this.masterAccountId);
}

/**
* It buys NFT by tokenId for given accountId
* @param {string} tokenId - The token ID of the NFT you want to buy.
* @param {string} accountId - The account ID of the account that wants to buy.
* @returns A boolean value.
*/
async buyForUser(tokenId: string, accountId: string): Promise<boolean> {
try {
await this.masterAccount.functionCall({
contractId: this.nftContractAccountId,
methodName: 'buy_for_user',
args: {
tokenId: tokenId,
accountId: accountId,
},
gas: this.gas,
attachedDeposit: '0' as any,
});

return true;
} catch (error) {
this.logger.error('Error executing contract function call: ', error);
}

return false;
}
}
40 changes: 39 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1565,6 +1565,15 @@ __metadata:
languageName: node
linkType: hard

"@types/bn.js@npm:^5.1.5":
version: 5.1.5
resolution: "@types/bn.js@npm:5.1.5"
dependencies:
"@types/node": "*"
checksum: c87b28c4af74545624f8a3dae5294b16aa190c222626e8d4b2e327b33b1a3f1eeb43e7a24d914a9774bca43d8cd6e1cb0325c1f4b3a244af6693a024e1d918e6
languageName: node
linkType: hard

"@types/body-parser@npm:*":
version: 1.19.2
resolution: "@types/body-parser@npm:1.19.2"
Expand Down Expand Up @@ -1763,6 +1772,15 @@ __metadata:
languageName: node
linkType: hard

"@types/node@npm:>=8.1.0":
version: 20.10.5
resolution: "@types/node@npm:20.10.5"
dependencies:
undici-types: ~5.26.4
checksum: e216b679f545a8356960ce985a0e53c3a58fff0eacd855e180b9e223b8db2b5bd07b744a002b8c1f0c37f9194648ab4578533b5c12df2ec10cc02f61d20948d2
languageName: node
linkType: hard

"@types/oauth@npm:*":
version: 0.9.1
resolution: "@types/oauth@npm:0.9.1"
Expand Down Expand Up @@ -2671,7 +2689,7 @@ __metadata:
languageName: node
linkType: hard

"bn.js@npm:5.2.1, bn.js@npm:^5.2.0":
"bn.js@npm:5.2.1, bn.js@npm:^5.2.0, bn.js@npm:^5.2.1":
version: 5.2.1
resolution: "bn.js@npm:5.2.1"
checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3
Expand Down Expand Up @@ -7122,6 +7140,7 @@ __metadata:
"@nestjs/testing": ^9.0.0
"@nestjs/typeorm": ^10.0.0
"@sendgrid/mail": ^7.7.0
"@types/bn.js": ^5.1.5
"@types/cron": ^2.0.1
"@types/express": ^4.17.13
"@types/jest": 29.2.4
Expand All @@ -7134,6 +7153,7 @@ __metadata:
"@typescript-eslint/parser": ^5.0.0
aws-sdk: ^2.1413.0
axios: ^1.4.0
bn.js: ^5.2.1
borsh: ^0.7.0
cache-manager: ^5.2.3
class-transformer: ^0.5.1
Expand All @@ -7155,6 +7175,7 @@ __metadata:
reflect-metadata: ^0.1.13
rxjs: ^7.2.0
source-map-support: ^0.5.20
stripe: ^14.9.0
supertest: ^6.1.3
ts-jest: 29.0.3
ts-loader: ^9.2.3
Expand Down Expand Up @@ -7826,6 +7847,16 @@ __metadata:
languageName: node
linkType: hard

"stripe@npm:^14.9.0":
version: 14.9.0
resolution: "stripe@npm:14.9.0"
dependencies:
"@types/node": ">=8.1.0"
qs: ^6.11.0
checksum: 3d7a9b8c70adcaeee5d37a4ad02310b3b16872ad68fe59f28a035d15d0514d6cef0a64bdd62245b4379772a83114a9abc50a5397948cef9a5c54388a62b0aaa6
languageName: node
linkType: hard

"superagent@npm:^8.0.5":
version: 8.0.9
resolution: "superagent@npm:8.0.9"
Expand Down Expand Up @@ -8392,6 +8423,13 @@ __metadata:
languageName: node
linkType: hard

"undici-types@npm:~5.26.4":
version: 5.26.5
resolution: "undici-types@npm:5.26.5"
checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487
languageName: node
linkType: hard

"unique-filename@npm:^3.0.0":
version: 3.0.0
resolution: "unique-filename@npm:3.0.0"
Expand Down

0 comments on commit 5c360ce

Please sign in to comment.