@dpa-oss/dpa 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/contracts/DPA.sol +58 -24
  2. package/package.json +1 -1
package/contracts/DPA.sol CHANGED
@@ -26,8 +26,8 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
26
26
  /// @notice The orchestrator address (only this address can mint/revise)
27
27
  address public orchestrator;
28
28
 
29
- /// @dev Token ID -> Token URI
30
- mapping(uint256 => string) private _tokenURIs;
29
+ /// @dev Token ID -> Token CID (Content Identifier)
30
+ mapping(uint256 => string) private _tokenCIDs;
31
31
 
32
32
  /// @dev Token ID -> Token content (encoded bytes, decoded by implementers)
33
33
  mapping(uint256 => bytes) private _tokenContents;
@@ -47,10 +47,13 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
47
47
  /// @dev Counter for total unique digital public assets (origin tokens only)
48
48
  uint256 private _totalAssets;
49
49
 
50
+ /// @dev Base URI for token metadata (used when individual URI is not set)
51
+ string private _baseTokenURI;
52
+
50
53
  // ============ Events ============
51
54
 
52
55
  /// @notice Emitted when a new token is minted
53
- event TokenMinted(uint256 indexed tokenId, address indexed to, string uri);
56
+ event TokenMinted(uint256 indexed tokenId, address indexed to, string cid);
54
57
 
55
58
  /// @notice Emitted when tokens are batch minted
56
59
  event BatchMinted(
@@ -73,6 +76,9 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
73
76
  address indexed newOrchestrator
74
77
  );
75
78
 
79
+ /// @notice Emitted when base URI is updated
80
+ event BaseURIUpdated(string previousURI, string newURI);
81
+
76
82
  /// @notice Emitted when a DPA contract is linked to a token
77
83
  event DPALinked(
78
84
  uint256 indexed tokenId,
@@ -156,18 +162,36 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
156
162
  _unpause();
157
163
  }
158
164
 
165
+ /**
166
+ * @notice Sets the base URI for token metadata
167
+ * @param baseURI_ New base URI (can be empty to disable)
168
+ */
169
+ function setBaseURI(string calldata baseURI_) external onlyOwner {
170
+ string memory previous = _baseTokenURI;
171
+ _baseTokenURI = baseURI_;
172
+ emit BaseURIUpdated(previous, baseURI_);
173
+ }
174
+
175
+ /**
176
+ * @notice Returns the current base URI
177
+ * @return The base URI string
178
+ */
179
+ function baseURI() external view returns (string memory) {
180
+ return _baseTokenURI;
181
+ }
182
+
159
183
  // ============ Minting Functions ============
160
184
 
161
185
  /**
162
- * @notice Mints a single token with URI and content
186
+ * @notice Mints a single token with CID and content
163
187
  * @param to Recipient address
164
- * @param uri Token URI (metadata location)
188
+ * @param cid Token CID (metadata CID)
165
189
  * @param content Encoded content data (decoded by derived contract)
166
190
  * @return tokenId The minted token ID
167
191
  */
168
192
  function mint(
169
193
  address to,
170
- string calldata uri,
194
+ string calldata cid,
171
195
  bytes calldata content
172
196
  )
173
197
  external
@@ -184,8 +208,8 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
184
208
  // Mint the token
185
209
  _mint(to, 1);
186
210
 
187
- // Store URI and content
188
- _tokenURIs[tokenId] = uri;
211
+ // Store CID and content
212
+ _tokenCIDs[tokenId] = cid;
189
213
  _tokenContents[tokenId] = content;
190
214
 
191
215
  // Create initial revision record (no parent, version 1)
@@ -201,21 +225,21 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
201
225
  // Increment total unique assets counter
202
226
  _totalAssets++;
203
227
 
204
- emit TokenMinted(tokenId, to, uri);
228
+ emit TokenMinted(tokenId, to, cid);
205
229
  }
206
230
 
207
231
  /**
208
232
  * @notice Mints a single token with explicit owner specification
209
233
  * @param to Recipient address
210
234
  * @param owner_ Token owner for record
211
- * @param uri Token URI
235
+ * @param cid Token CID (metadata CID)
212
236
  * @param content Encoded content data
213
237
  * @return tokenId The minted token ID
214
238
  */
215
239
  function mintWithOwner(
216
240
  address to,
217
241
  address owner_,
218
- string calldata uri,
242
+ string calldata cid,
219
243
  bytes calldata content
220
244
  )
221
245
  external
@@ -229,7 +253,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
229
253
  _validateContent(content);
230
254
  _mint(to, 1);
231
255
 
232
- _tokenURIs[tokenId] = uri;
256
+ _tokenCIDs[tokenId] = cid;
233
257
  _tokenContents[tokenId] = content;
234
258
 
235
259
  _revisions[tokenId] = Types.RevisionRecord({
@@ -244,19 +268,19 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
244
268
  // Increment total unique assets counter
245
269
  _totalAssets++;
246
270
 
247
- emit TokenMinted(tokenId, to, uri);
271
+ emit TokenMinted(tokenId, to, cid);
248
272
  }
249
273
 
250
274
  /**
251
275
  * @notice Batch mints tokens with URIs and contents
252
276
  * @param to Recipient address (same for all tokens in batch)
253
- * @param uris Array of token URIs
277
+ * @param cids Array of token CIDs
254
278
  * @param contents Array of encoded content data
255
279
  * @return startTokenId The first token ID in the batch
256
280
  */
257
281
  function batchMint(
258
282
  address to,
259
- string[] calldata uris,
283
+ string[] calldata cids,
260
284
  bytes[] calldata contents
261
285
  )
262
286
  external
@@ -265,7 +289,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
265
289
  nonReentrant
266
290
  returns (uint256 startTokenId)
267
291
  {
268
- uint256 quantity = uris.length;
292
+ uint256 quantity = cids.length;
269
293
 
270
294
  if (quantity != contents.length) {
271
295
  revert Errors.ArrayLengthMismatch();
@@ -287,7 +311,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
287
311
  // Store URIs, contents, and create revision records
288
312
  for (uint256 i = 0; i < quantity; i++) {
289
313
  uint256 tokenId = startTokenId + i;
290
- _tokenURIs[tokenId] = uris[i];
314
+ _tokenCIDs[tokenId] = cids[i];
291
315
  _tokenContents[tokenId] = contents[i];
292
316
 
293
317
  _revisions[tokenId] = Types.RevisionRecord({
@@ -299,7 +323,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
299
323
  actor: msg.sender
300
324
  });
301
325
 
302
- emit TokenMinted(tokenId, to, uris[i]);
326
+ emit TokenMinted(tokenId, to, cids[i]);
303
327
  }
304
328
 
305
329
  // Increment total unique assets counter by batch size
@@ -313,14 +337,14 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
313
337
  /**
314
338
  * @notice Creates a new revision of an existing token (protocol-enforced)
315
339
  * @param parentTokenId The token being revised (must be latest version)
316
- * @param uri New token URI
340
+ * @param cid New token CID
317
341
  * @param content New encoded content
318
342
  * @param reason Human-readable reason (stored as hash, emitted in full)
319
343
  * @return newTokenId The newly minted revision token
320
344
  */
321
345
  function revise(
322
346
  uint256 parentTokenId,
323
- string calldata uri,
347
+ string calldata cid,
324
348
  bytes calldata content,
325
349
  string calldata reason
326
350
  )
@@ -330,7 +354,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
330
354
  nonReentrant
331
355
  returns (uint256 newTokenId)
332
356
  {
333
- newTokenId = _revise(parentTokenId, uri, content, reason);
357
+ newTokenId = _revise(parentTokenId, cid, content, reason);
334
358
  }
335
359
 
336
360
  /**
@@ -338,7 +362,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
338
362
  */
339
363
  function _revise(
340
364
  uint256 parentTokenId,
341
- string calldata uri,
365
+ string calldata cid,
342
366
  bytes calldata content,
343
367
  string calldata reason
344
368
  ) internal onlyLatestVersion(parentTokenId) returns (uint256 newTokenId) {
@@ -353,7 +377,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
353
377
  _mint(parentOwner, 1);
354
378
 
355
379
  // Store new token data
356
- _tokenURIs[newTokenId] = uri;
380
+ _tokenCIDs[newTokenId] = cid;
357
381
  _tokenContents[newTokenId] = content;
358
382
 
359
383
  // Find origin token (root of chain)
@@ -394,7 +418,17 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
394
418
  if (!_exists(tokenId)) {
395
419
  revert Errors.InvalidTokenId();
396
420
  }
397
- return _tokenURIs[tokenId];
421
+
422
+ string memory _tokenCID = _tokenCIDs[tokenId];
423
+ string memory base = _baseTokenURI;
424
+
425
+ // If base URI is set, concatenate with token path/CID
426
+ if (bytes(base).length > 0 && bytes(_tokenCID).length > 0) {
427
+ return string(abi.encodePacked(base, _tokenCID));
428
+ }
429
+
430
+ // Return token CID as-is (full URI or path)
431
+ return _tokenCID;
398
432
  }
399
433
 
400
434
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dpa-oss/dpa",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "scripts": {
5
5
  "compile": "hardhat compile",
6
6
  "test": "hardhat test",