@nina-protocol/nina-db 0.0.104 → 0.0.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/models/Release.js +27 -11
- package/dist/models/Transaction.js +2 -0
- package/package.json +4 -3
- package/src/migrations/20250616215722_program_id.js +19 -0
- package/src/migrations/20250630215722_transaction_program_id.js +19 -0
- package/src/models/Release.js +26 -12
- package/src/models/Transaction.js +2 -0
package/dist/models/Release.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as anchorSerum from '@project-serum/anchor';
|
|
2
|
+
import * as anchorCoral from '@coral-xyz/anchor';
|
|
2
3
|
import { Metaplex } from '@metaplex-foundation/js';
|
|
3
4
|
import { Model } from 'objection';
|
|
4
5
|
import { stripHtmlIfNeeded, tweetNewRelease } from '../utils/index.js';
|
|
@@ -10,6 +11,7 @@ import Tag from './Tag.js';
|
|
|
10
11
|
import axios from 'axios';
|
|
11
12
|
import promiseRetry from 'promise-retry';
|
|
12
13
|
import { customAlphabet } from 'nanoid';
|
|
14
|
+
import { getTokenMetadata } from '@solana/spl-token';
|
|
13
15
|
const ensureHttps = (uri) => {
|
|
14
16
|
if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
|
|
15
17
|
return `https://${uri}`;
|
|
@@ -52,21 +54,25 @@ export default class Release extends Model {
|
|
|
52
54
|
archived: { type: 'boolean' },
|
|
53
55
|
},
|
|
54
56
|
};
|
|
55
|
-
static findOrCreate = async (publicKey, hubPublicKey = null) => {
|
|
57
|
+
static findOrCreate = async (publicKey, hubPublicKey = null, programId = process.env.NINA_PROGRAM_V2_ID) => {
|
|
56
58
|
try {
|
|
59
|
+
console.log('Release.findOrCreate', publicKey, programId);
|
|
57
60
|
let release = await Release.query().findOne({ publicKey });
|
|
58
61
|
if (release) {
|
|
62
|
+
console.log('release found', release);
|
|
59
63
|
return release;
|
|
60
64
|
}
|
|
65
|
+
let anchor = programId === process.env.NINA_PROGRAM_V2_ID ? anchorCoral : anchorSerum;
|
|
61
66
|
const connection = new anchor.web3.Connection(process.env.SOLANA_CLUSTER_URL);
|
|
62
67
|
const provider = new anchor.AnchorProvider(connection, {}, { commitment: 'confirmed' });
|
|
63
|
-
const program = await anchor.Program.at(
|
|
68
|
+
const program = await anchor.Program.at(programId, provider);
|
|
69
|
+
const programModelName = programId === process.env.NINA_PROGRAM_V2_ID ? 'releaseV2' : 'release';
|
|
64
70
|
const metaplex = new Metaplex(connection);
|
|
65
71
|
let attempts = 0;
|
|
66
72
|
const releaseAccount = await promiseRetry(async (retry) => {
|
|
67
73
|
try {
|
|
68
74
|
attempts += 1;
|
|
69
|
-
const result = await program.account.
|
|
75
|
+
const result = await program.account[programModelName].fetch(new anchor.web3.PublicKey(publicKey), 'confirmed');
|
|
70
76
|
return result;
|
|
71
77
|
}
|
|
72
78
|
catch (error) {
|
|
@@ -78,7 +84,13 @@ export default class Release extends Model {
|
|
|
78
84
|
minTimeout: 500,
|
|
79
85
|
maxTimeout: 1500,
|
|
80
86
|
});
|
|
81
|
-
let metadataAccount
|
|
87
|
+
let metadataAccount;
|
|
88
|
+
if (programId === process.env.NINA_PROGRAM_V2_ID) {
|
|
89
|
+
metadataAccount = await getTokenMetadata(connection, releaseAccount.mint, 'confirmed');
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
metadataAccount = (await metaplex.nfts().findAllByMintList({ mints: [releaseAccount.releaseMint] }, { commitment: 'confirmed' }))[0];
|
|
93
|
+
}
|
|
82
94
|
if (!metadataAccount) {
|
|
83
95
|
throw new Error('No metadata account found for release - is not a complete release');
|
|
84
96
|
}
|
|
@@ -93,12 +105,13 @@ export default class Release extends Model {
|
|
|
93
105
|
let publisher = await Account.findOrCreate(releaseAccount.authority.toBase58());
|
|
94
106
|
release = await this.createRelease({
|
|
95
107
|
publicKey,
|
|
96
|
-
mint: releaseAccount.releaseMint.toBase58(),
|
|
108
|
+
mint: programId === process.env.NINA_PROGRAM_V2_ID ? releaseAccount.mint.toBase58() : releaseAccount.releaseMint.toBase58(),
|
|
97
109
|
metadata: json,
|
|
98
|
-
datetime: new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
|
|
110
|
+
datetime: programId === process.env.NINA_PROGRAM_V2_ID ? new Date().toISOString() : new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
|
|
99
111
|
slug,
|
|
100
112
|
publisherId: publisher.id,
|
|
101
|
-
releaseAccount
|
|
113
|
+
releaseAccount,
|
|
114
|
+
programId,
|
|
102
115
|
});
|
|
103
116
|
if (hubPublicKey) {
|
|
104
117
|
const hub = await Hub.query().findOne({ publicKey: hubPublicKey });
|
|
@@ -114,7 +127,7 @@ export default class Release extends Model {
|
|
|
114
127
|
return null;
|
|
115
128
|
}
|
|
116
129
|
};
|
|
117
|
-
static createRelease = async ({ publicKey, mint, metadata, datetime, publisherId, releaseAccount }) => {
|
|
130
|
+
static createRelease = async ({ publicKey, mint, metadata, datetime, publisherId, releaseAccount, programId }) => {
|
|
118
131
|
const slug = await this.generateSlug(metadata);
|
|
119
132
|
const price = releaseAccount.account?.price?.toNumber() || releaseAccount?.price?.toNumber() || 0;
|
|
120
133
|
const paymentMint = releaseAccount.account?.paymentMint.toBase58() || releaseAccount?.paymentMint.toBase58();
|
|
@@ -127,7 +140,8 @@ export default class Release extends Model {
|
|
|
127
140
|
publisherId,
|
|
128
141
|
price: `${price}`,
|
|
129
142
|
paymentMint,
|
|
130
|
-
archived: false
|
|
143
|
+
archived: false,
|
|
144
|
+
programId,
|
|
131
145
|
});
|
|
132
146
|
if (metadata.properties.tags) {
|
|
133
147
|
for await (let tag of metadata.properties.tags) {
|
|
@@ -135,7 +149,9 @@ export default class Release extends Model {
|
|
|
135
149
|
await Release.relatedQuery('tags').for(release.id).relate(tagRecord.id).onConflict(['tagId', 'releaseId']).ignore();
|
|
136
150
|
}
|
|
137
151
|
}
|
|
138
|
-
|
|
152
|
+
if (programId === process.env.NINA_PROGRAM_ID) {
|
|
153
|
+
await this.processRevenueShares(releaseAccount, release);
|
|
154
|
+
}
|
|
139
155
|
tweetNewRelease(metadata, publisherId, slug);
|
|
140
156
|
return release;
|
|
141
157
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nina-protocol/nina-db",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.106",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "src/index.js",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
|
|
24
24
|
"@babel/preset-es2015": "^7.0.0-beta.53",
|
|
25
25
|
"@metaplex-foundation/js": "^0.18.1",
|
|
26
|
-
"@
|
|
26
|
+
"@coral-xyz/anchor": "^0.31.0",
|
|
27
|
+
"@solana/spl-token": "^0.4.9",
|
|
27
28
|
"axios": "^0.27.2",
|
|
28
29
|
"knex": "^2.2.0",
|
|
29
30
|
"nanoid": "^4.0.2",
|
|
@@ -46,6 +47,6 @@
|
|
|
46
47
|
"rollup-plugin-babel": "^4.4.0",
|
|
47
48
|
"rollup-plugin-commonjs": "^10.1.0",
|
|
48
49
|
"rollup-plugin-terser": "^7.0.2",
|
|
49
|
-
"typescript": "
|
|
50
|
+
"typescript": "5.7.3"
|
|
50
51
|
}
|
|
51
52
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param { import("knex").Knex } knex
|
|
3
|
+
* @returns { Promise<void> }
|
|
4
|
+
*/
|
|
5
|
+
export const up = function(knex) {
|
|
6
|
+
return knex.schema.table('releases', table => {
|
|
7
|
+
table.string('programId').notNullable().defaultTo(process.env.NINA_PROGRAM_ID);
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param { import("knex").Knex } knex
|
|
13
|
+
* @returns { Promise<void> }
|
|
14
|
+
*/
|
|
15
|
+
export const down = function(knex) {
|
|
16
|
+
return knex.schema.table('releases', table => {
|
|
17
|
+
table.dropColumn('programId');
|
|
18
|
+
});
|
|
19
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param { import("knex").Knex } knex
|
|
3
|
+
* @returns { Promise<void> }
|
|
4
|
+
*/
|
|
5
|
+
export const up = function(knex) {
|
|
6
|
+
return knex.schema.table('transactions', table => {
|
|
7
|
+
table.string('programId').notNullable().defaultTo(process.env.NINA_PROGRAM_ID);
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param { import("knex").Knex } knex
|
|
13
|
+
* @returns { Promise<void> }
|
|
14
|
+
*/
|
|
15
|
+
export const down = function(knex) {
|
|
16
|
+
return knex.schema.table('transactions', table => {
|
|
17
|
+
table.dropColumn('programId');
|
|
18
|
+
});
|
|
19
|
+
};
|
package/src/models/Release.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as anchorSerum from '@project-serum/anchor';
|
|
2
|
+
import * as anchorCoral from '@coral-xyz/anchor';
|
|
2
3
|
import { Metaplex } from '@metaplex-foundation/js';
|
|
3
4
|
import { Model } from 'objection';
|
|
4
5
|
import { stripHtmlIfNeeded, tweetNewRelease }from '../utils/index.js';
|
|
@@ -10,6 +11,7 @@ import Tag from './Tag.js';
|
|
|
10
11
|
import axios from 'axios';
|
|
11
12
|
import promiseRetry from 'promise-retry';
|
|
12
13
|
import { customAlphabet } from 'nanoid';
|
|
14
|
+
import { getTokenMetadata } from '@solana/spl-token';
|
|
13
15
|
|
|
14
16
|
const ensureHttps = (uri) => {
|
|
15
17
|
if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
|
|
@@ -56,27 +58,30 @@ export default class Release extends Model {
|
|
|
56
58
|
},
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
static findOrCreate = async (publicKey, hubPublicKey=null) => {
|
|
61
|
+
static findOrCreate = async (publicKey, hubPublicKey=null, programId=process.env.NINA_PROGRAM_V2_ID) => {
|
|
60
62
|
try {
|
|
63
|
+
console.log('Release.findOrCreate', publicKey, programId)
|
|
61
64
|
let release = await Release.query().findOne({ publicKey });
|
|
62
65
|
if (release) {
|
|
66
|
+
console.log('release found', release)
|
|
63
67
|
return release;
|
|
64
68
|
}
|
|
65
69
|
|
|
70
|
+
let anchor = programId === process.env.NINA_PROGRAM_V2_ID ? anchorCoral : anchorSerum;
|
|
66
71
|
const connection = new anchor.web3.Connection(process.env.SOLANA_CLUSTER_URL);
|
|
67
72
|
const provider = new anchor.AnchorProvider(connection, {}, {commitment: 'confirmed'})
|
|
68
73
|
const program = await anchor.Program.at(
|
|
69
|
-
|
|
74
|
+
programId,
|
|
70
75
|
provider,
|
|
71
76
|
)
|
|
77
|
+
const programModelName = programId === process.env.NINA_PROGRAM_V2_ID ? 'releaseV2' : 'release';
|
|
72
78
|
const metaplex = new Metaplex(connection);
|
|
73
79
|
let attempts = 0;
|
|
74
|
-
|
|
75
80
|
const releaseAccount = await promiseRetry(
|
|
76
81
|
async (retry) => {
|
|
77
82
|
try {
|
|
78
83
|
attempts += 1
|
|
79
|
-
const result = await program.account.
|
|
84
|
+
const result = await program.account[programModelName].fetch(new anchor.web3.PublicKey(publicKey), 'confirmed')
|
|
80
85
|
return result
|
|
81
86
|
} catch (error) {
|
|
82
87
|
console.log('error fetching release account', error)
|
|
@@ -89,7 +94,12 @@ export default class Release extends Model {
|
|
|
89
94
|
}
|
|
90
95
|
)
|
|
91
96
|
|
|
92
|
-
let metadataAccount
|
|
97
|
+
let metadataAccount
|
|
98
|
+
if (programId === process.env.NINA_PROGRAM_V2_ID) {
|
|
99
|
+
metadataAccount = await getTokenMetadata(connection, releaseAccount.mint, 'confirmed')
|
|
100
|
+
} else {
|
|
101
|
+
metadataAccount = (await metaplex.nfts().findAllByMintList({mints: [releaseAccount.releaseMint]}, { commitment: 'confirmed' }))[0];
|
|
102
|
+
}
|
|
93
103
|
if (!metadataAccount) {
|
|
94
104
|
throw new Error('No metadata account found for release - is not a complete release')
|
|
95
105
|
}
|
|
@@ -104,12 +114,13 @@ export default class Release extends Model {
|
|
|
104
114
|
let publisher = await Account.findOrCreate(releaseAccount.authority.toBase58());
|
|
105
115
|
release = await this.createRelease({
|
|
106
116
|
publicKey,
|
|
107
|
-
mint: releaseAccount.releaseMint.toBase58(),
|
|
117
|
+
mint: programId === process.env.NINA_PROGRAM_V2_ID ? releaseAccount.mint.toBase58() : releaseAccount.releaseMint.toBase58(),
|
|
108
118
|
metadata: json,
|
|
109
|
-
datetime: new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
|
|
119
|
+
datetime: programId === process.env.NINA_PROGRAM_V2_ID ? new Date().toISOString() : new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
|
|
110
120
|
slug,
|
|
111
121
|
publisherId: publisher.id,
|
|
112
|
-
releaseAccount
|
|
122
|
+
releaseAccount,
|
|
123
|
+
programId,
|
|
113
124
|
});
|
|
114
125
|
|
|
115
126
|
if (hubPublicKey) {
|
|
@@ -128,7 +139,7 @@ export default class Release extends Model {
|
|
|
128
139
|
}
|
|
129
140
|
}
|
|
130
141
|
|
|
131
|
-
static createRelease = async ({publicKey, mint, metadata, datetime, publisherId, releaseAccount}) => {
|
|
142
|
+
static createRelease = async ({publicKey, mint, metadata, datetime, publisherId, releaseAccount, programId}) => {
|
|
132
143
|
const slug = await this.generateSlug(metadata);
|
|
133
144
|
const price = releaseAccount.account?.price?.toNumber() || releaseAccount?.price?.toNumber() || 0;
|
|
134
145
|
const paymentMint = releaseAccount.account?.paymentMint.toBase58() || releaseAccount?.paymentMint.toBase58();
|
|
@@ -141,7 +152,8 @@ export default class Release extends Model {
|
|
|
141
152
|
publisherId,
|
|
142
153
|
price: `${price}`,
|
|
143
154
|
paymentMint,
|
|
144
|
-
archived: false
|
|
155
|
+
archived: false,
|
|
156
|
+
programId,
|
|
145
157
|
})
|
|
146
158
|
if (metadata.properties.tags) {
|
|
147
159
|
for await (let tag of metadata.properties.tags) {
|
|
@@ -149,7 +161,9 @@ export default class Release extends Model {
|
|
|
149
161
|
await Release.relatedQuery('tags').for(release.id).relate(tagRecord.id).onConflict(['tagId', 'releaseId']).ignore();
|
|
150
162
|
}
|
|
151
163
|
}
|
|
152
|
-
|
|
164
|
+
if (programId === process.env.NINA_PROGRAM_ID) {
|
|
165
|
+
await this.processRevenueShares(releaseAccount, release);
|
|
166
|
+
}
|
|
153
167
|
tweetNewRelease(metadata, publisherId, slug);
|
|
154
168
|
return release;
|
|
155
169
|
}
|