Skip to content

Commit 3bb0213

Browse files
CoveMBericglau
andauthored
[Stellar] add token URI setting (#725)
Co-authored-by: Eric Lau <ericglau@outlook.com>
1 parent ae017e8 commit 3bb0213

File tree

12 files changed

+95
-18
lines changed

12 files changed

+95
-18
lines changed

.changeset/brown-walls-roll.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@openzeppelin/wizard-stellar': patch
3+
'@openzeppelin/wizard-common': patch
4+
'@openzeppelin/contracts-mcp': patch
5+
---
6+
7+
Add tokenUri setting for stellar non fungible model

packages/common/src/ai/descriptions/stellar.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const stellarNonFungibleDescriptions = {
2222
enumerable: 'Whether the NFTs are enumerable (can be iterated over).',
2323
consecutive: 'To batch mint NFTs instead of minting them individually (sequential minting is mandatory).',
2424
sequential: 'Whether the IDs of the minted NFTs will be sequential.',
25+
tokenUri: 'The metadata URI returned by the token contract for every NFT.',
2526
};
2627

2728
export const stellarStablecoinDescriptions = {

packages/core/stellar/src/generate/non-fungible.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const booleans = [true, false];
88
const blueprint = {
99
name: ['MyToken'],
1010
symbol: ['MTK'],
11+
tokenUri: ['https://www.mytoken.com'],
1112
burnable: booleans,
1213
pausable: booleans,
1314
upgradeable: booleans,

packages/core/stellar/src/non-fungible.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ testNonFungible('non-fungible - complex name', {
153153
pausable: true,
154154
});
155155

156+
testNonFungible('non-fungible custom token uri', {
157+
tokenUri: 'https://example.com/nfts/',
158+
});
159+
156160
testAPIEquivalence('non-fungible API default');
157161

158162
testAPIEquivalence('non-fungible API basic', { name: 'CustomToken', symbol: 'CTK' });

packages/core/stellar/src/non-fungible.test.ts.md

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Generated by [AVA](https://avajs.dev).
2222
#[contractimpl]␊
2323
impl MyToken {␊
2424
pub fn __constructor(e: &Env) {␊
25-
let uri = String::from_str(e, "www.mytoken.com");␊
25+
let uri = String::from_str(e, "https://www.mytoken.com");␊
2626
let name = String::from_str(e, "MyToken");␊
2727
let symbol = String::from_str(e, "MTK");␊
2828
Base::set_metadata(e, uri, name, symbol);␊
@@ -55,7 +55,7 @@ Generated by [AVA](https://avajs.dev).
5555
#[contractimpl]␊
5656
impl MyToken {␊
5757
pub fn __constructor(e: &Env) {␊
58-
let uri = String::from_str(e, "www.mytoken.com");␊
58+
let uri = String::from_str(e, "https://www.mytoken.com");␊
5959
let name = String::from_str(e, "MyToken");␊
6060
let symbol = String::from_str(e, "MTK");␊
6161
Base::set_metadata(e, uri, name, symbol);␊
@@ -98,7 +98,7 @@ Generated by [AVA](https://avajs.dev).
9898
#[contractimpl]␊
9999
impl MyToken {␊
100100
pub fn __constructor(e: &Env, owner: Address) {␊
101-
let uri = String::from_str(e, "www.mytoken.com");␊
101+
let uri = String::from_str(e, "https://www.mytoken.com");␊
102102
let name = String::from_str(e, "MyToken");␊
103103
let symbol = String::from_str(e, "MTK");␊
104104
Base::set_metadata(e, uri, name, symbol);␊
@@ -168,7 +168,7 @@ Generated by [AVA](https://avajs.dev).
168168
#[contractimpl]␊
169169
impl MyToken {␊
170170
pub fn __constructor(e: &Env, owner: Address) {␊
171-
let uri = String::from_str(e, "www.mytoken.com");␊
171+
let uri = String::from_str(e, "https://www.mytoken.com");␊
172172
let name = String::from_str(e, "MyToken");␊
173173
let symbol = String::from_str(e, "MTK");␊
174174
Base::set_metadata(e, uri, name, symbol);␊
@@ -254,7 +254,7 @@ Generated by [AVA](https://avajs.dev).
254254
#[contractimpl]␊
255255
impl MyToken {␊
256256
pub fn __constructor(e: &Env, owner: Address) {␊
257-
let uri = String::from_str(e, "www.mytoken.com");␊
257+
let uri = String::from_str(e, "https://www.mytoken.com");␊
258258
let name = String::from_str(e, "MyToken");␊
259259
let symbol = String::from_str(e, "MTK");␊
260260
Base::set_metadata(e, uri, name, symbol);␊
@@ -303,7 +303,7 @@ Generated by [AVA](https://avajs.dev).
303303
#[contractimpl]␊
304304
impl MyToken {␊
305305
pub fn __constructor(e: &Env) {␊
306-
let uri = String::from_str(e, "www.mytoken.com");␊
306+
let uri = String::from_str(e, "https://www.mytoken.com");␊
307307
let name = String::from_str(e, "MyToken");␊
308308
let symbol = String::from_str(e, "MTK");␊
309309
Base::set_metadata(e, uri, name, symbol);␊
@@ -347,7 +347,7 @@ Generated by [AVA](https://avajs.dev).
347347
#[contractimpl]␊
348348
impl MyToken {␊
349349
pub fn __constructor(e: &Env, owner: Address) {␊
350-
let uri = String::from_str(e, "www.mytoken.com");␊
350+
let uri = String::from_str(e, "https://www.mytoken.com");␊
351351
let name = String::from_str(e, "MyToken");␊
352352
let symbol = String::from_str(e, "MTK");␊
353353
Base::set_metadata(e, uri, name, symbol);␊
@@ -405,7 +405,7 @@ Generated by [AVA](https://avajs.dev).
405405
#[contractimpl]␊
406406
impl MyToken {␊
407407
pub fn __constructor(e: &Env, owner: Address) {␊
408-
let uri = String::from_str(e, "www.mytoken.com");␊
408+
let uri = String::from_str(e, "https://www.mytoken.com");␊
409409
let name = String::from_str(e, "MyToken");␊
410410
let symbol = String::from_str(e, "MTK");␊
411411
Base::set_metadata(e, uri, name, symbol);␊
@@ -467,7 +467,7 @@ Generated by [AVA](https://avajs.dev).
467467
#[contractimpl]␊
468468
impl MyToken {␊
469469
pub fn __constructor(e: &Env, owner: Address) {␊
470-
let uri = String::from_str(e, "www.mytoken.com");␊
470+
let uri = String::from_str(e, "https://www.mytoken.com");␊
471471
let name = String::from_str(e, "MyToken");␊
472472
let symbol = String::from_str(e, "MTK");␊
473473
Base::set_metadata(e, uri, name, symbol);␊
@@ -553,7 +553,7 @@ Generated by [AVA](https://avajs.dev).
553553
#[contractimpl]␊
554554
impl MyToken {␊
555555
pub fn __constructor(e: &Env, owner: Address) {␊
556-
let uri = String::from_str(e, "www.mytoken.com");␊
556+
let uri = String::from_str(e, "https://www.mytoken.com");␊
557557
let name = String::from_str(e, "MyToken");␊
558558
let symbol = String::from_str(e, "MTK");␊
559559
Base::set_metadata(e, uri, name, symbol);␊
@@ -647,7 +647,7 @@ Generated by [AVA](https://avajs.dev).
647647
#[contractimpl]␊
648648
impl MyToken {␊
649649
pub fn __constructor(e: &Env) {␊
650-
let uri = String::from_str(e, "www.mytoken.com");␊
650+
let uri = String::from_str(e, "https://www.mytoken.com");␊
651651
let name = String::from_str(e, "MyToken");␊
652652
let symbol = String::from_str(e, "MTK");␊
653653
Base::set_metadata(e, uri, name, symbol);␊
@@ -683,7 +683,7 @@ Generated by [AVA](https://avajs.dev).
683683
#[contractimpl]␊
684684
impl MyToken {␊
685685
pub fn __constructor(e: &Env, owner: Address) {␊
686-
let uri = String::from_str(e, "www.mytoken.com");␊
686+
let uri = String::from_str(e, "https://www.mytoken.com");␊
687687
let name = String::from_str(e, "MyToken");␊
688688
let symbol = String::from_str(e, "MTK");␊
689689
Base::set_metadata(e, uri, name, symbol);␊
@@ -739,7 +739,7 @@ Generated by [AVA](https://avajs.dev).
739739
#[contractimpl]␊
740740
impl MyToken {␊
741741
pub fn __constructor(e: &Env, owner: Address) {␊
742-
let uri = String::from_str(e, "www.mytoken.com");␊
742+
let uri = String::from_str(e, "https://www.mytoken.com");␊
743743
let name = String::from_str(e, "MyToken");␊
744744
let symbol = String::from_str(e, "MTK");␊
745745
Base::set_metadata(e, uri, name, symbol);␊
@@ -842,7 +842,7 @@ Generated by [AVA](https://avajs.dev).
842842
#[contractimpl]␊
843843
impl CustomToken {␊
844844
pub fn __constructor(e: &Env, owner: Address) {␊
845-
let uri = String::from_str(e, "www.mytoken.com");␊
845+
let uri = String::from_str(e, "https://www.mytoken.com");␊
846846
let name = String::from_str(e, "Custom $ Token");␊
847847
let symbol = String::from_str(e, "MTK");␊
848848
Base::set_metadata(e, uri, name, symbol);␊
@@ -908,3 +908,36 @@ Generated by [AVA](https://avajs.dev).
908908
#[contractimpl]␊
909909
impl Ownable for CustomToken {}␊
910910
`
911+
912+
## non-fungible custom token uri
913+
914+
> Snapshot 1
915+
916+
`// SPDX-License-Identifier: MIT␊
917+
// Compatible with OpenZeppelin Stellar Soroban Contracts ^0.4.1␊
918+
#![no_std]␊
919+
920+
use soroban_sdk::{contract, contractimpl, Env, String};␊
921+
use stellar_macros::default_impl;␊
922+
use stellar_tokens::non_fungible::{Base, NonFungibleToken};␊
923+
924+
#[contract]␊
925+
pub struct MyToken;␊
926+
927+
#[contractimpl]␊
928+
impl MyToken {␊
929+
pub fn __constructor(e: &Env) {␊
930+
let uri = String::from_str(e, "https://example.com/nfts/");␊
931+
let name = String::from_str(e, "MyToken");␊
932+
let symbol = String::from_str(e, "MTK");␊
933+
Base::set_metadata(e, uri, name, symbol);␊
934+
}␊
935+
}␊
936+
937+
#[default_impl]␊
938+
#[contractimpl]␊
939+
impl NonFungibleToken for MyToken {␊
940+
type ContractType = Base;␊
941+
942+
}␊
943+
`
50 Bytes
Binary file not shown.

packages/core/stellar/src/non-fungible.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { toByteArray } from './utils/convert-strings';
1616
export const defaults: Required<NonFungibleOptions> = {
1717
name: 'MyToken',
1818
symbol: 'MTK',
19+
tokenUri: 'https://www.mytoken.com',
1920
burnable: false,
2021
enumerable: false,
2122
consecutive: false,
@@ -34,6 +35,7 @@ export function printNonFungible(opts: NonFungibleOptions = defaults): string {
3435
export interface NonFungibleOptions extends CommonContractOptions {
3536
name: string;
3637
symbol: string;
38+
tokenUri?: string;
3739
burnable?: boolean;
3840
enumerable?: boolean;
3941
consecutive?: boolean;
@@ -47,6 +49,7 @@ function withDefaults(opts: NonFungibleOptions): Required<NonFungibleOptions> {
4749
return {
4850
...opts,
4951
...withCommonContractDefaults(opts),
52+
tokenUri: opts.tokenUri ?? defaults.tokenUri,
5053
burnable: opts.burnable ?? defaults.burnable,
5154
consecutive: opts.consecutive ?? defaults.consecutive,
5255
enumerable: opts.enumerable ?? defaults.enumerable,
@@ -87,7 +90,7 @@ export function buildNonFungible(opts: NonFungibleOptions): Contract {
8790
throw new OptionsError(errors);
8891
}
8992

90-
addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol), allOpts.pausable);
93+
addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol), toByteArray(allOpts.tokenUri), allOpts.pausable);
9194

9295
if (allOpts.pausable) {
9396
addPausable(c, allOpts.access);
@@ -119,9 +122,9 @@ export function buildNonFungible(opts: NonFungibleOptions): Contract {
119122
return c;
120123
}
121124

122-
function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boolean) {
125+
function addBase(c: ContractBuilder, name: string, symbol: string, tokenUri: string, pausable: boolean) {
123126
// Set metadata
124-
c.addConstructorCode('let uri = String::from_str(e, "www.mytoken.com");');
127+
c.addConstructorCode(`let uri = String::from_str(e, "${tokenUri}");`);
125128
c.addConstructorCode(`let name = String::from_str(e, "${name}");`);
126129
c.addConstructorCode(`let symbol = String::from_str(e, "${symbol}");`);
127130
c.addConstructorCode(`Base::set_metadata(e, uri, name, symbol);`);

packages/mcp/src/stellar/schemas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export const stablecoinSchema = {
5757
export const nonFungibleSchema = {
5858
name: z.string().describe(commonDescriptions.name),
5959
symbol: z.string().describe(commonDescriptions.symbol),
60+
tokenUri: z.string().optional().describe(stellarNonFungibleDescriptions.tokenUri),
6061
burnable: z.boolean().optional().describe(commonDescriptions.burnable),
6162
enumerable: z.boolean().optional().describe(stellarNonFungibleDescriptions.enumerable),
6263
consecutive: z.boolean().optional().describe(stellarNonFungibleDescriptions.consecutive),

packages/mcp/src/stellar/tools/non-fungible.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ test('basic', async t => {
3434
const params: z.infer<typeof t.context.schema> = {
3535
name: 'TestToken',
3636
symbol: 'TST',
37+
tokenUri: 'https://example.com/nft/',
3738
};
3839
await assertAPIEquivalence(t, params, nonFungible.print);
3940
});
@@ -42,6 +43,7 @@ test('all', async t => {
4243
const params: DeepRequired<z.infer<typeof t.context.schema>> = {
4344
name: 'TestToken',
4445
symbol: 'TST',
46+
tokenUri: 'https://example.com/nft/',
4547
burnable: true,
4648
enumerable: true,
4749
consecutive: true,

packages/mcp/src/stellar/tools/non-fungible.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,23 @@ export function registerStellarNonFungible(server: McpServer): RegisteredTool {
1010
'stellar-non-fungible',
1111
makeDetailedPrompt(stellarPrompts.NonFungible),
1212
nonFungibleSchema,
13-
async ({ name, symbol, burnable, enumerable, consecutive, pausable, mintable, sequential, upgradeable, info }) => {
13+
async ({
14+
name,
15+
symbol,
16+
tokenUri,
17+
burnable,
18+
enumerable,
19+
consecutive,
20+
pausable,
21+
mintable,
22+
sequential,
23+
upgradeable,
24+
info,
25+
}) => {
1426
const opts: NonFungibleOptions = {
1527
name,
1628
symbol,
29+
tokenUri,
1730
burnable,
1831
enumerable,
1932
consecutive,

0 commit comments

Comments
 (0)