@medialane/sdk 0.197.0 → 0.199.0
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/README.md +85 -39
- package/dist/chains-CmwjZVU7.d.cts +85 -0
- package/dist/chains-CmwjZVU7.d.ts +85 -0
- package/dist/chunk-3HPMEDYH.cjs +967 -0
- package/dist/chunk-3HPMEDYH.cjs.map +1 -0
- package/dist/{chunk-3ME5YKTW.js → chunk-5KY6P434.js} +2 -2
- package/dist/chunk-5KY6P434.js.map +1 -0
- package/dist/chunk-F7W6IWTL.js +660 -0
- package/dist/chunk-F7W6IWTL.js.map +1 -0
- package/dist/chunk-GIBIHGSV.js +916 -0
- package/dist/chunk-GIBIHGSV.js.map +1 -0
- package/dist/chunk-GV4A2WNO.js +444 -0
- package/dist/chunk-GV4A2WNO.js.map +1 -0
- package/dist/{chunk-7EYJC5CB.cjs → chunk-H2NJB3AK.cjs} +2 -2
- package/dist/chunk-H2NJB3AK.cjs.map +1 -0
- package/dist/chunk-KGAGWULG.js +932 -0
- package/dist/chunk-KGAGWULG.js.map +1 -0
- package/dist/chunk-MEJ47LC3.cjs +463 -0
- package/dist/chunk-MEJ47LC3.cjs.map +1 -0
- package/dist/chunk-W76AZ5WC.cjs +376 -0
- package/dist/chunk-W76AZ5WC.cjs.map +1 -0
- package/dist/chunk-WRBXQPRL.js +323 -0
- package/dist/chunk-WRBXQPRL.js.map +1 -0
- package/dist/chunk-ZLMIHQWM.cjs +975 -0
- package/dist/chunk-ZLMIHQWM.cjs.map +1 -0
- package/dist/chunk-ZVANOWIB.cjs +688 -0
- package/dist/chunk-ZVANOWIB.cjs.map +1 -0
- package/dist/contract/index.cjs +88 -261
- package/dist/contract/index.cjs.map +1 -1
- package/dist/contract/index.d.cts +139 -4
- package/dist/contract/index.d.ts +139 -4
- package/dist/contract/index.js +4 -220
- package/dist/contract/index.js.map +1 -1
- package/dist/evm/index.cjs +3 -3
- package/dist/evm/index.d.cts +2 -1
- package/dist/evm/index.d.ts +2 -1
- package/dist/evm/index.js +1 -1
- package/dist/fetch-Cx9Pr7-B.d.cts +3 -0
- package/dist/fetch-Cx9Pr7-B.d.ts +3 -0
- package/dist/index.cjs +180 -834
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -131
- package/dist/index.d.ts +54 -131
- package/dist/index.js +8 -660
- package/dist/index.js.map +1 -1
- package/dist/passkey-errors-Bu6I_5rn.d.ts +1041 -0
- package/dist/passkey-errors-D0XNQ3_g.d.cts +1041 -0
- package/dist/provisioning-CwRkCN8D.d.cts +14 -0
- package/dist/provisioning-CwRkCN8D.d.ts +14 -0
- package/dist/{provisioning-BUYiU8Tr.d.ts → responses-BLpM_cH_.d.cts} +40 -48
- package/dist/{provisioning-BUYiU8Tr.d.cts → responses-BLpM_cH_.d.ts} +40 -48
- package/dist/server/index.cjs +117 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +98 -0
- package/dist/server/index.d.ts +98 -0
- package/dist/server/index.js +4 -0
- package/dist/server/index.js.map +1 -0
- package/dist/services-C9CkOsYi.d.cts +728 -0
- package/dist/services-CI62hzNf.d.ts +728 -0
- package/dist/solana/index.cjs +2 -2
- package/dist/solana/index.d.cts +2 -1
- package/dist/solana/index.d.ts +2 -1
- package/dist/solana/index.js +1 -1
- package/dist/starknet/index.cjs +898 -1729
- package/dist/starknet/index.cjs.map +1 -1
- package/dist/starknet/index.d.cts +98 -467
- package/dist/starknet/index.d.ts +98 -467
- package/dist/starknet/index.js +704 -1680
- package/dist/starknet/index.js.map +1 -1
- package/dist/stellar/index.cjs +2 -2
- package/dist/stellar/index.d.cts +2 -1
- package/dist/stellar/index.d.ts +2 -1
- package/dist/stellar/index.js +1 -1
- package/dist/types-BW6ktwcT.d.ts +71 -0
- package/dist/types-BftPOVEJ.d.cts +71 -0
- package/dist/wallet/index.cjs +240 -0
- package/dist/wallet/index.cjs.map +1 -0
- package/dist/wallet/index.d.cts +319 -0
- package/dist/wallet/index.d.ts +319 -0
- package/dist/wallet/index.js +7 -0
- package/dist/wallet/index.js.map +1 -0
- package/package.json +13 -2
- package/dist/chunk-2R7XBA34.cjs +0 -1938
- package/dist/chunk-2R7XBA34.cjs.map +0 -1
- package/dist/chunk-3ME5YKTW.js.map +0 -1
- package/dist/chunk-6WVUUBFI.js +0 -1853
- package/dist/chunk-6WVUUBFI.js.map +0 -1
- package/dist/chunk-7EYJC5CB.cjs.map +0 -1
- package/dist/errors-CZm-NZK0.d.cts +0 -1754
- package/dist/errors-h6H6cj3Q.d.ts +0 -1754
- package/dist/types-DC4jNPAF.d.cts +0 -153
- package/dist/types-DC4jNPAF.d.ts +0 -153
package/dist/starknet/index.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import {
|
|
1
|
+
import { resolveConfig, getService, collectionHref, dropHref, stringifyBigInts } from '../chunk-GV4A2WNO.js';
|
|
2
|
+
export { InvalidPairingPayloadError, InvalidRecoveryKeyError, InvalidStarkPrivateKeyError, SponsoredCallRejectedError, accountFor, allowsFallbackFunding, buildAddOwnerCall, buildCancelEscapeCall, buildCompleteEscapeOwnerCall, buildDeployAccountParams, buildRemoveOwnerByGuidCall, buildRemoveOwnerCall, buildSetFirstGuardianCall, buildTriggerEscapeOwnerCall, canRemoveDevice, claimSessionWallet, completeDeployment, computeAccountAddress, computeOwnerGuid, createDeploymentCoordinator, createMediaWallet, createOwnerStore, createPasskeyOwner, createSelfFundConsent, decodeEscapeAndStatus, decodeGuardiansInfo, deploySelfFunded, deploySponsored, deriveAesKey, deriveOwnerKeyPair, describeDevices, describeGuardianStatus, describeRecoveryAction, encodePairingPayload, encodeRecoveryKey, erc20Balance, estimateSelfFundedFee, executeSponsored, generateStarkKeyPair, getEscape, getEscapeSecurityPeriod, getGuardians, getOwners, indexedDbDeviceKeys, isDeployed, isValidStarknetAddress, normalizeWalletAddress, ownerConstructorCalldata, parseAccountAddress, parsePairingPayload, parseRecoveryKey, sealPrivateKey, selfFundedExecutor, signWithPrivateKey, sponsoredExecutor, starkKeyPairFromPrivateKey, unsealPrivateKey, waitUntilDeployed } from '../chunk-GIBIHGSV.js';
|
|
3
|
+
import { ApiClient, UserFacingError, normalizeAddress, SUPPORTED_TOKENS, MedialaneError, MedialaneApiError } from '../chunk-KGAGWULG.js';
|
|
4
|
+
export { DeviceKeyMissingError, MedialaneError, PasskeyCancelledError, PasskeyUnsupportedError, UserFacingError } from '../chunk-KGAGWULG.js';
|
|
5
|
+
import { getStarknetCoordinates } from '../chunk-5KY6P434.js';
|
|
6
|
+
import '../chunk-WRBXQPRL.js';
|
|
4
7
|
import '../chunk-PZ5AY32C.js';
|
|
5
|
-
import { CallData,
|
|
6
|
-
import { extract, expand } from '@noble/hashes/hkdf.js';
|
|
7
|
-
import { sha256 } from '@noble/hashes/sha2.js';
|
|
8
|
+
import { hash, CallData, RpcProvider, cairo, num, CairoOption, CairoOptionVariant, uint256, TypedDataRevision, Contract, byteArray, constants, shortString } from 'starknet';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.name = "MedialaneError";
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// src/starknet/marketplace/utils.ts
|
|
20
|
-
var START_TIME_BUFFER_SECS = 30;
|
|
21
|
-
function newContract(abi, address, providerOrAccount) {
|
|
22
|
-
const C = Contract;
|
|
23
|
-
return C.length === 1 ? new Contract({ abi, address, providerOrAccount }) : new Contract(
|
|
24
|
-
abi,
|
|
25
|
-
address,
|
|
26
|
-
providerOrAccount
|
|
27
|
-
);
|
|
10
|
+
function createChainProvider(backendUrl, apiKey) {
|
|
11
|
+
return new RpcProvider({
|
|
12
|
+
nodeUrl: `${backendUrl.replace(/\/$/, "")}/v1/rpc`,
|
|
13
|
+
headers: apiKey ? { "x-api-key": apiKey } : {},
|
|
14
|
+
blockIdentifier: "latest"
|
|
15
|
+
});
|
|
28
16
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
|
|
18
|
+
// src/starknet/client.ts
|
|
19
|
+
var NO_BACKEND = "backendUrl not configured. Pass backendUrl to MedialaneClient to use";
|
|
20
|
+
var MedialaneClient = class {
|
|
21
|
+
constructor(rawConfig = {}) {
|
|
22
|
+
this.config = resolveConfig(rawConfig);
|
|
23
|
+
const config = this.config;
|
|
24
|
+
this.api = config.backendUrl ? new ApiClient({ baseUrl: config.backendUrl, apiKey: config.apiKey, retry: config.retryOptions, chain: config.chain }) : new ApiClient({
|
|
25
|
+
baseUrl: "https://medialane-sdk-no-backend.invalid",
|
|
26
|
+
apiKey: config.apiKey,
|
|
27
|
+
fetch: () => {
|
|
28
|
+
throw new Error(`${NO_BACKEND} .api`);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
32
|
+
get chain() {
|
|
33
|
+
return this.config.chain;
|
|
34
|
+
}
|
|
35
|
+
get provider() {
|
|
36
|
+
if (!this.config.backendUrl) {
|
|
37
|
+
throw new Error(`${NO_BACKEND} .provider`);
|
|
38
|
+
}
|
|
39
|
+
return this._provider ?? (this._provider = createChainProvider(this.config.backendUrl, this.config.apiKey));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
42
|
|
|
43
43
|
// src/starknet/abis/ipMarketplace.ts
|
|
44
44
|
var IPMarketplaceABI = [
|
|
@@ -10376,975 +10376,148 @@ var IPGenesisABI = [
|
|
|
10376
10376
|
]
|
|
10377
10377
|
}
|
|
10378
10378
|
];
|
|
10379
|
-
var
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10383
|
-
|
|
10384
|
-
|
|
10379
|
+
var START_TIME_BUFFER_SECS = 30;
|
|
10380
|
+
function newContract(abi, address, providerOrAccount) {
|
|
10381
|
+
const C = Contract;
|
|
10382
|
+
return C.length === 1 ? new Contract({ abi, address, providerOrAccount }) : new Contract(
|
|
10383
|
+
abi,
|
|
10384
|
+
address,
|
|
10385
|
+
providerOrAccount
|
|
10386
|
+
);
|
|
10385
10387
|
}
|
|
10386
|
-
function
|
|
10387
|
-
|
|
10388
|
-
|
|
10389
|
-
leaves.forEach((leaf, i) => tree[tree.length - 1 - i] = leaf);
|
|
10390
|
-
for (let i = tree.length - 1 - leaves.length; i >= 0; i--) {
|
|
10391
|
-
tree[i] = nodeHash(tree[2 * i + 1], tree[2 * i + 2]);
|
|
10388
|
+
function getChainId(config) {
|
|
10389
|
+
if (config.chain !== "STARKNET") {
|
|
10390
|
+
throw new Error(`SNIP-12 signing is Starknet-only; got chain "${config.chain}"`);
|
|
10392
10391
|
}
|
|
10392
|
+
return constants.StarknetChainId.SN_MAIN;
|
|
10393
|
+
}
|
|
10394
|
+
function resolveToken(currency) {
|
|
10395
|
+
const token = SUPPORTED_TOKENS.find(
|
|
10396
|
+
(t) => t.symbol === currency.toUpperCase() || t.address.toLowerCase() === currency.toLowerCase()
|
|
10397
|
+
);
|
|
10398
|
+
if (!token) throw new MedialaneError(`Unsupported currency: ${currency}`, "INVALID_PARAMS");
|
|
10399
|
+
return token;
|
|
10400
|
+
}
|
|
10401
|
+
var STARKNET_DOMAIN = [
|
|
10402
|
+
{ name: "name", type: "shortstring" },
|
|
10403
|
+
{ name: "version", type: "shortstring" },
|
|
10404
|
+
{ name: "chainId", type: "shortstring" },
|
|
10405
|
+
{ name: "revision", type: "shortstring" }
|
|
10406
|
+
];
|
|
10407
|
+
var OFFER_ITEM = [
|
|
10408
|
+
{ name: "item_type", type: "shortstring" },
|
|
10409
|
+
{ name: "token", type: "ContractAddress" },
|
|
10410
|
+
{ name: "identifier_or_criteria", type: "felt" },
|
|
10411
|
+
{ name: "amount", type: "felt" }
|
|
10412
|
+
];
|
|
10413
|
+
var CONSIDERATION_ITEM = [
|
|
10414
|
+
{ name: "item_type", type: "shortstring" },
|
|
10415
|
+
{ name: "token", type: "ContractAddress" },
|
|
10416
|
+
{ name: "identifier_or_criteria", type: "felt" },
|
|
10417
|
+
{ name: "amount", type: "felt" },
|
|
10418
|
+
{ name: "recipient", type: "ContractAddress" }
|
|
10419
|
+
];
|
|
10420
|
+
var ORDER_PARAMETERS = [
|
|
10421
|
+
{ name: "offerer", type: "ContractAddress" },
|
|
10422
|
+
{ name: "marketplace", type: "ContractAddress" },
|
|
10423
|
+
{ name: "offer", type: "OfferItem" },
|
|
10424
|
+
{ name: "consideration", type: "ConsiderationItem" },
|
|
10425
|
+
{ name: "royalty_max_bps", type: "felt" },
|
|
10426
|
+
{ name: "start_time", type: "felt" },
|
|
10427
|
+
{ name: "end_time", type: "felt" },
|
|
10428
|
+
{ name: "salt", type: "felt" },
|
|
10429
|
+
{ name: "counter", type: "felt" }
|
|
10430
|
+
];
|
|
10431
|
+
var ORDER_CANCELLATION = [
|
|
10432
|
+
{ name: "order_hash", type: "felt" },
|
|
10433
|
+
{ name: "offerer", type: "ContractAddress" }
|
|
10434
|
+
];
|
|
10435
|
+
var DOMAIN_VERSION = {
|
|
10436
|
+
erc721: "5",
|
|
10437
|
+
erc1155: "4"
|
|
10438
|
+
};
|
|
10439
|
+
function buildDomain(standard, chainId) {
|
|
10393
10440
|
return {
|
|
10394
|
-
|
|
10395
|
-
|
|
10396
|
-
|
|
10397
|
-
|
|
10398
|
-
const proof = [];
|
|
10399
|
-
while (i > 0) {
|
|
10400
|
-
proof.push(tree[i % 2 === 1 ? i + 1 : i - 1]);
|
|
10401
|
-
i = Math.floor((i - 1) / 2);
|
|
10402
|
-
}
|
|
10403
|
-
return proof;
|
|
10404
|
-
}
|
|
10441
|
+
name: "Medialane",
|
|
10442
|
+
version: DOMAIN_VERSION[standard],
|
|
10443
|
+
chainId,
|
|
10444
|
+
revision: TypedDataRevision.ACTIVE
|
|
10405
10445
|
};
|
|
10406
10446
|
}
|
|
10407
|
-
function
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
return computed === BigInt(root);
|
|
10447
|
+
function buildOrderTypedData(message, chainId) {
|
|
10448
|
+
return {
|
|
10449
|
+
domain: buildDomain("erc721", chainId),
|
|
10450
|
+
primaryType: "OrderParameters",
|
|
10451
|
+
types: {
|
|
10452
|
+
StarknetDomain: STARKNET_DOMAIN,
|
|
10453
|
+
OrderParameters: ORDER_PARAMETERS,
|
|
10454
|
+
OfferItem: OFFER_ITEM,
|
|
10455
|
+
ConsiderationItem: CONSIDERATION_ITEM
|
|
10456
|
+
},
|
|
10457
|
+
message
|
|
10458
|
+
};
|
|
10420
10459
|
}
|
|
10421
|
-
function
|
|
10422
|
-
return
|
|
10460
|
+
function build1155OrderTypedData(message, chainId) {
|
|
10461
|
+
return {
|
|
10462
|
+
domain: buildDomain("erc1155", chainId),
|
|
10463
|
+
primaryType: "OrderParameters",
|
|
10464
|
+
types: {
|
|
10465
|
+
StarknetDomain: STARKNET_DOMAIN,
|
|
10466
|
+
OrderParameters: ORDER_PARAMETERS,
|
|
10467
|
+
OfferItem: OFFER_ITEM,
|
|
10468
|
+
ConsiderationItem: CONSIDERATION_ITEM
|
|
10469
|
+
},
|
|
10470
|
+
message
|
|
10471
|
+
};
|
|
10423
10472
|
}
|
|
10424
|
-
function
|
|
10425
|
-
|
|
10426
|
-
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
10473
|
+
function buildCancellationTypedData(message, chainId) {
|
|
10474
|
+
return {
|
|
10475
|
+
domain: buildDomain("erc721", chainId),
|
|
10476
|
+
primaryType: "OrderCancellation",
|
|
10477
|
+
types: {
|
|
10478
|
+
StarknetDomain: STARKNET_DOMAIN,
|
|
10479
|
+
OrderCancellation: ORDER_CANCELLATION
|
|
10480
|
+
},
|
|
10481
|
+
message
|
|
10482
|
+
};
|
|
10430
10483
|
}
|
|
10431
|
-
|
|
10432
|
-
|
|
10433
|
-
|
|
10434
|
-
|
|
10435
|
-
|
|
10436
|
-
|
|
10437
|
-
|
|
10438
|
-
|
|
10484
|
+
function build1155CancellationTypedData(message, chainId) {
|
|
10485
|
+
return {
|
|
10486
|
+
domain: buildDomain("erc1155", chainId),
|
|
10487
|
+
primaryType: "OrderCancellation",
|
|
10488
|
+
types: {
|
|
10489
|
+
StarknetDomain: STARKNET_DOMAIN,
|
|
10490
|
+
OrderCancellation: ORDER_CANCELLATION
|
|
10491
|
+
},
|
|
10492
|
+
message
|
|
10493
|
+
};
|
|
10439
10494
|
}
|
|
10440
|
-
function
|
|
10441
|
-
|
|
10495
|
+
function feeBps(surface, cfg) {
|
|
10496
|
+
if (!cfg.enabled || !cfg.fundAddress) return 0;
|
|
10497
|
+
return surface === "marketplace" ? cfg.marketplaceBps : surface === "launchpad" ? cfg.launchpadBps : cfg.sponsorshipBps;
|
|
10442
10498
|
}
|
|
10443
|
-
|
|
10444
|
-
|
|
10445
|
-
const [root, end] = await Promise.all([
|
|
10446
|
-
provider.callContract({ contractAddress, entrypoint: "allowlist_root", calldata: [] }),
|
|
10447
|
-
provider.callContract({ contractAddress, entrypoint: "claim_end_time", calldata: [] })
|
|
10448
|
-
]);
|
|
10449
|
-
return { root: root[0] ?? "0x0", claimEndTime: Number(BigInt(end[0] ?? "0x0")) };
|
|
10499
|
+
function feeAmount(grossAmount, bps) {
|
|
10500
|
+
return bps <= 0 ? 0n : grossAmount * BigInt(bps) / 10000n;
|
|
10450
10501
|
}
|
|
10451
|
-
function
|
|
10452
|
-
const
|
|
10453
|
-
if (
|
|
10454
|
-
|
|
10455
|
-
|
|
10456
|
-
|
|
10457
|
-
|
|
10458
|
-
|
|
10459
|
-
|
|
10460
|
-
}
|
|
10461
|
-
var addr = (a) => normalizeAddress("STARKNET", a);
|
|
10462
|
-
var byteArrayFelts = (s) => CallData.compile([byteArray.byteArrayFromString(s)]);
|
|
10463
|
-
var popCalls = {
|
|
10464
|
-
claim(collection, proof) {
|
|
10465
|
-
return { contractAddress: addr(collection), entrypoint: "claim", calldata: [String(proof.length), ...proof] };
|
|
10466
|
-
},
|
|
10467
|
-
/** An empty `tokenUri` uses the collection's URI. */
|
|
10468
|
-
issue(collection, recipient, tokenUri = "") {
|
|
10469
|
-
return { contractAddress: addr(collection), entrypoint: "issue", calldata: [addr(recipient), ...byteArrayFelts(tokenUri)] };
|
|
10470
|
-
},
|
|
10471
|
-
/** Only the token's holder can burn it. */
|
|
10472
|
-
burn(collection, tokenId) {
|
|
10473
|
-
const id = cairo.uint256(BigInt(tokenId));
|
|
10474
|
-
return { contractAddress: addr(collection), entrypoint: "burn", calldata: [String(id.low), String(id.high)] };
|
|
10475
|
-
},
|
|
10476
|
-
setAllowlistRoot(collection, root) {
|
|
10477
|
-
return { contractAddress: addr(collection), entrypoint: "set_allowlist_root", calldata: [root] };
|
|
10478
|
-
}
|
|
10479
|
-
};
|
|
10480
|
-
|
|
10481
|
-
// src/starknet/services/pop.ts
|
|
10482
|
-
var PopService = class {
|
|
10483
|
-
constructor(config) {
|
|
10484
|
-
this.factoryAddress = getStarknetCoordinates(config.chain).popFactory;
|
|
10485
|
-
}
|
|
10486
|
-
async createCollection(account, params) {
|
|
10487
|
-
const factory = newContract(POPFactoryABI, this.factoryAddress, account);
|
|
10488
|
-
const call = factory.populate("create_collection", [params.name, params.symbol, params.baseUri, params.claimEndTime]);
|
|
10489
|
-
const res = await account.execute([call]);
|
|
10490
|
-
return { txHash: res.transaction_hash };
|
|
10491
|
-
}
|
|
10492
|
-
async setAllowlistRoot(account, params) {
|
|
10493
|
-
const call = popCalls.setAllowlistRoot(params.collection, params.root);
|
|
10494
|
-
const res = await account.execute([call]);
|
|
10495
|
-
return { txHash: res.transaction_hash };
|
|
10496
|
-
}
|
|
10497
|
-
async claim(account, params) {
|
|
10498
|
-
const call = popCalls.claim(params.collection, params.proof);
|
|
10499
|
-
const res = await account.execute([call]);
|
|
10500
|
-
return { txHash: res.transaction_hash };
|
|
10501
|
-
}
|
|
10502
|
-
async issue(account, params) {
|
|
10503
|
-
const call = popCalls.issue(params.collection, params.recipient, params.tokenUri);
|
|
10504
|
-
const res = await account.execute([call]);
|
|
10505
|
-
return { txHash: res.transaction_hash };
|
|
10506
|
-
}
|
|
10507
|
-
/** Destroys the caller's own credential; the address cannot receive another from this collection. */
|
|
10508
|
-
async burn(account, params) {
|
|
10509
|
-
const call = popCalls.burn(params.collection, params.tokenId);
|
|
10510
|
-
const res = await account.execute([call]);
|
|
10511
|
-
return { txHash: res.transaction_hash };
|
|
10512
|
-
}
|
|
10513
|
-
};
|
|
10514
|
-
async function popHasClaimed(provider, collection, address) {
|
|
10515
|
-
const res = await provider.callContract({
|
|
10516
|
-
contractAddress: normalizeAddress("STARKNET", collection),
|
|
10517
|
-
entrypoint: "has_claimed",
|
|
10518
|
-
calldata: [normalizeAddress("STARKNET", address)]
|
|
10519
|
-
});
|
|
10520
|
-
return BigInt(res[0] ?? "0x0") !== 0n;
|
|
10521
|
-
}
|
|
10522
|
-
function feeBps(surface, cfg) {
|
|
10523
|
-
if (!cfg.enabled || !cfg.fundAddress) return 0;
|
|
10524
|
-
return surface === "marketplace" ? cfg.marketplaceBps : surface === "launchpad" ? cfg.launchpadBps : cfg.sponsorshipBps;
|
|
10525
|
-
}
|
|
10526
|
-
function feeAmount(grossAmount, bps) {
|
|
10527
|
-
return bps <= 0 ? 0n : grossAmount * BigInt(bps) / 10000n;
|
|
10528
|
-
}
|
|
10529
|
-
function buildFeeCall(p, cfg) {
|
|
10530
|
-
const fee = feeAmount(p.grossAmount, feeBps(p.surface, cfg));
|
|
10531
|
-
if (fee <= 0n) return null;
|
|
10532
|
-
const u = cairo.uint256(fee.toString());
|
|
10533
|
-
return {
|
|
10534
|
-
contractAddress: p.token,
|
|
10535
|
-
entrypoint: "transfer",
|
|
10536
|
-
calldata: [cfg.fundAddress, u.low.toString(), u.high.toString()]
|
|
10537
|
-
};
|
|
10538
|
-
}
|
|
10539
|
-
var DROP_MAX_CLAIM_QUANTITY = 50n;
|
|
10540
|
-
var addr2 = (a) => normalizeAddress("STARKNET", a);
|
|
10541
|
-
var factoryData = new CallData(DropFactoryABI);
|
|
10542
|
-
var collectionData = new CallData(DropCollectionABI);
|
|
10543
|
-
function toContractTerms(t) {
|
|
10544
|
-
const price = BigInt(t.price);
|
|
10545
|
-
return {
|
|
10546
|
-
start_time: t.startTime,
|
|
10547
|
-
end_time: t.endTime,
|
|
10548
|
-
price: cairo.uint256(price),
|
|
10549
|
-
payment_token: price === 0n ? "0x0" : addr2(t.paymentToken),
|
|
10550
|
-
max_per_wallet: cairo.uint256(BigInt(t.maxPerWallet))
|
|
10551
|
-
};
|
|
10552
|
-
}
|
|
10553
|
-
var dropCalls = {
|
|
10554
|
-
create(factory, p) {
|
|
10555
|
-
return {
|
|
10556
|
-
contractAddress: addr2(factory),
|
|
10557
|
-
entrypoint: "create_drop",
|
|
10558
|
-
calldata: factoryData.compile("create_drop", {
|
|
10559
|
-
name: p.name,
|
|
10560
|
-
symbol: p.symbol,
|
|
10561
|
-
base_uri: p.baseUri,
|
|
10562
|
-
max_supply: cairo.uint256(BigInt(p.maxSupply)),
|
|
10563
|
-
terms: toContractTerms(p.terms),
|
|
10564
|
-
allowlist_root: p.allowlistRoot ?? "0x0"
|
|
10565
|
-
})
|
|
10566
|
-
};
|
|
10567
|
-
},
|
|
10568
|
-
/** Approve (paid drops) and claim. The platform fee call is added by the caller. */
|
|
10569
|
-
claim(collection, p) {
|
|
10570
|
-
const quantity = BigInt(p.quantity);
|
|
10571
|
-
if (quantity < 1n || quantity > DROP_MAX_CLAIM_QUANTITY) throw new RangeError(`quantity must be 1 to ${DROP_MAX_CLAIM_QUANTITY}`);
|
|
10572
|
-
const total = BigInt(p.price) * quantity;
|
|
10573
|
-
const calls = [];
|
|
10574
|
-
if (total > 0n) {
|
|
10575
|
-
calls.push({
|
|
10576
|
-
contractAddress: addr2(p.paymentToken),
|
|
10577
|
-
entrypoint: "approve",
|
|
10578
|
-
calldata: CallData.compile([addr2(collection), cairo.uint256(total)])
|
|
10579
|
-
});
|
|
10580
|
-
}
|
|
10581
|
-
calls.push({
|
|
10582
|
-
contractAddress: addr2(collection),
|
|
10583
|
-
entrypoint: "claim",
|
|
10584
|
-
calldata: collectionData.compile("claim", { quantity: cairo.uint256(quantity), proof: p.proof ?? [] })
|
|
10585
|
-
});
|
|
10586
|
-
return calls;
|
|
10587
|
-
},
|
|
10588
|
-
/** Organizer only: free mint within the supply cap. */
|
|
10589
|
-
issue(collection, recipient, quantity) {
|
|
10590
|
-
const q = BigInt(quantity);
|
|
10591
|
-
if (q < 1n) throw new RangeError("quantity must be at least 1");
|
|
10592
|
-
return {
|
|
10593
|
-
contractAddress: addr2(collection),
|
|
10594
|
-
entrypoint: "issue",
|
|
10595
|
-
calldata: collectionData.compile("issue", { recipient: addr2(recipient), quantity: cairo.uint256(q) })
|
|
10596
|
-
};
|
|
10597
|
-
},
|
|
10598
|
-
/** Organizer only. 0 opens the drop to everyone. */
|
|
10599
|
-
setAllowlistRoot(collection, root) {
|
|
10600
|
-
return { contractAddress: addr2(collection), entrypoint: "set_allowlist_root", calldata: collectionData.compile("set_allowlist_root", { root }) };
|
|
10601
|
-
}
|
|
10602
|
-
};
|
|
10603
|
-
function dropMintCost(price, quantity, feeBps2) {
|
|
10604
|
-
const subtotal = BigInt(price) * BigInt(quantity);
|
|
10605
|
-
const fee = feeAmount(subtotal, feeBps2);
|
|
10606
|
-
return { subtotal, fee, total: subtotal + fee };
|
|
10607
|
-
}
|
|
10608
|
-
|
|
10609
|
-
// src/starknet/drop-state.ts
|
|
10610
|
-
var hex = (v) => normalizeAddress("STARKNET", v ?? "0x0");
|
|
10611
|
-
var u256 = (low, high) => BigInt(low ?? "0x0") + (BigInt(high ?? "0x0") << 128n);
|
|
10612
|
-
async function readDrop(provider, collection) {
|
|
10613
|
-
const contractAddress = hex(collection);
|
|
10614
|
-
const read = (entrypoint) => provider.callContract({ contractAddress, entrypoint, calldata: [] });
|
|
10615
|
-
const [organizer, terms, root, max, minted] = await Promise.all([
|
|
10616
|
-
read("organizer"),
|
|
10617
|
-
read("terms"),
|
|
10618
|
-
read("allowlist_root"),
|
|
10619
|
-
read("max_supply"),
|
|
10620
|
-
read("total_minted")
|
|
10621
|
-
]);
|
|
10622
|
-
return {
|
|
10623
|
-
organizer: hex(organizer[0]),
|
|
10624
|
-
startTime: Number(BigInt(terms[0] ?? "0x0")),
|
|
10625
|
-
endTime: Number(BigInt(terms[1] ?? "0x0")),
|
|
10626
|
-
price: u256(terms[2], terms[3]),
|
|
10627
|
-
paymentToken: hex(terms[4]),
|
|
10628
|
-
maxPerWallet: u256(terms[5], terms[6]),
|
|
10629
|
-
allowlistRoot: root[0] ?? "0x0",
|
|
10630
|
-
maxSupply: u256(max[0], max[1]),
|
|
10631
|
-
totalMinted: u256(minted[0], minted[1])
|
|
10632
|
-
};
|
|
10633
|
-
}
|
|
10634
|
-
async function dropClaimedBy(provider, collection, wallet) {
|
|
10635
|
-
const res = await provider.callContract({ contractAddress: hex(collection), entrypoint: "claimed_by", calldata: [hex(wallet)] });
|
|
10636
|
-
return u256(res[0], res[1]);
|
|
10637
|
-
}
|
|
10638
|
-
function dropMintState(input) {
|
|
10639
|
-
const none = (state) => ({ state, maxQuantity: 0n });
|
|
10640
|
-
const { drop, wallet, claimed, proof, balance, now } = input;
|
|
10641
|
-
if (!drop) return none("loading");
|
|
10642
|
-
if (drop.startTime !== 0 && now < drop.startTime) return none("upcoming");
|
|
10643
|
-
if (drop.endTime !== 0 && now > drop.endTime) return none("ended");
|
|
10644
|
-
const supplyLeft = drop.maxSupply === 0n ? null : drop.maxSupply - drop.totalMinted;
|
|
10645
|
-
if (supplyLeft !== null && supplyLeft <= 0n) return none("sold-out");
|
|
10646
|
-
if (!wallet) return none("no-wallet");
|
|
10647
|
-
if (BigInt(drop.allowlistRoot) !== 0n) {
|
|
10648
|
-
if (proof === null) return none("no-link");
|
|
10649
|
-
if (!verifyPopProof(drop.allowlistRoot, wallet, proof)) return none("not-on-list");
|
|
10650
|
-
}
|
|
10651
|
-
if (claimed === null) return none("loading");
|
|
10652
|
-
const walletLeft = drop.maxPerWallet === 0n ? null : drop.maxPerWallet - claimed;
|
|
10653
|
-
if (walletLeft !== null && walletLeft <= 0n) return none("limit-reached");
|
|
10654
|
-
let max = DROP_MAX_CLAIM_QUANTITY;
|
|
10655
|
-
if (supplyLeft !== null && supplyLeft < max) max = supplyLeft;
|
|
10656
|
-
if (walletLeft !== null && walletLeft < max) max = walletLeft;
|
|
10657
|
-
if (drop.price > 0n) {
|
|
10658
|
-
if (balance === null) return none("loading");
|
|
10659
|
-
while (max > 0n && dropMintCost(drop.price, max, input.feeBps).total > balance) max--;
|
|
10660
|
-
if (max === 0n) return none("insufficient-balance");
|
|
10661
|
-
}
|
|
10662
|
-
return { state: "ready", maxQuantity: max };
|
|
10663
|
-
}
|
|
10664
|
-
function dropClaimLinks(origin, collection, list) {
|
|
10665
|
-
const base = `${origin}${dropHref(collection)}`;
|
|
10666
|
-
return Object.entries(list.proofs).map(([address, proof]) => ({
|
|
10667
|
-
address,
|
|
10668
|
-
url: `${base}${encodePopClaimFragment(proof)}`
|
|
10669
|
-
}));
|
|
10670
|
-
}
|
|
10671
|
-
|
|
10672
|
-
// src/starknet/services/drop.ts
|
|
10673
|
-
var DropService = class {
|
|
10674
|
-
constructor(config) {
|
|
10675
|
-
this.factoryAddress = getStarknetCoordinates(config.chain).dropFactory;
|
|
10676
|
-
this.config = config;
|
|
10677
|
-
}
|
|
10678
|
-
async createDrop(account, params) {
|
|
10679
|
-
const res = await account.execute([dropCalls.create(this.factoryAddress, params)]);
|
|
10680
|
-
return { txHash: res.transaction_hash };
|
|
10681
|
-
}
|
|
10682
|
-
/** Mints `quantity` to the account, paying the drop's price and the platform fee. */
|
|
10683
|
-
async claim(account, params) {
|
|
10684
|
-
const drop = await readDrop(account.provider, params.collection);
|
|
10685
|
-
const calls = dropCalls.claim(params.collection, {
|
|
10686
|
-
quantity: params.quantity,
|
|
10687
|
-
proof: params.proof,
|
|
10688
|
-
price: drop.price,
|
|
10689
|
-
paymentToken: drop.paymentToken
|
|
10690
|
-
});
|
|
10691
|
-
const fee = drop.price > 0n ? buildFeeCall(
|
|
10692
|
-
{ surface: "launchpad", token: drop.paymentToken, grossAmount: drop.price * BigInt(params.quantity) },
|
|
10693
|
-
this.config.feeConfig
|
|
10694
|
-
) : null;
|
|
10695
|
-
const res = await account.execute(fee ? [...calls, fee] : calls);
|
|
10696
|
-
return { txHash: res.transaction_hash };
|
|
10697
|
-
}
|
|
10698
|
-
async issue(account, params) {
|
|
10699
|
-
const res = await account.execute([dropCalls.issue(params.collection, params.recipient, params.quantity)]);
|
|
10700
|
-
return { txHash: res.transaction_hash };
|
|
10701
|
-
}
|
|
10702
|
-
async setAllowlistRoot(account, params) {
|
|
10703
|
-
const res = await account.execute([dropCalls.setAllowlistRoot(params.collection, params.root)]);
|
|
10704
|
-
return { txHash: res.transaction_hash };
|
|
10705
|
-
}
|
|
10706
|
-
};
|
|
10707
|
-
|
|
10708
|
-
// src/starknet/services/erc1155collection.ts
|
|
10709
|
-
var ERC1155CollectionService = class {
|
|
10710
|
-
constructor(config) {
|
|
10711
|
-
this.factoryAddress = config.collection1155Contract ?? getStarknetCoordinates(config.chain).collection1155;
|
|
10712
|
-
}
|
|
10713
|
-
_factory(account) {
|
|
10714
|
-
return newContract(
|
|
10715
|
-
IPCollection1155FactoryABI,
|
|
10716
|
-
normalizeAddress("STARKNET", this.factoryAddress),
|
|
10717
|
-
account
|
|
10718
|
-
);
|
|
10719
|
-
}
|
|
10720
|
-
_collection(address, account) {
|
|
10721
|
-
return newContract(
|
|
10722
|
-
IPCollection1155ABI,
|
|
10723
|
-
normalizeAddress("STARKNET", address),
|
|
10724
|
-
account
|
|
10725
|
-
);
|
|
10726
|
-
}
|
|
10727
|
-
async deployCollection(account, params) {
|
|
10728
|
-
const factory = this._factory(account);
|
|
10729
|
-
const call = factory.populate("deploy_collection", [params.name, params.symbol, params.baseUri]);
|
|
10730
|
-
const res = await account.execute([call]);
|
|
10731
|
-
return { txHash: res.transaction_hash };
|
|
10732
|
-
}
|
|
10733
|
-
async mintEdition(account, params) {
|
|
10734
|
-
const collection = this._collection(params.collection, account);
|
|
10735
|
-
const call = collection.populate("mint_edition", [
|
|
10736
|
-
params.to,
|
|
10737
|
-
BigInt(params.value),
|
|
10738
|
-
params.tokenUri
|
|
10739
|
-
]);
|
|
10740
|
-
const res = await account.execute([call]);
|
|
10741
|
-
return { txHash: res.transaction_hash };
|
|
10742
|
-
}
|
|
10743
|
-
async batchMintEdition(account, params) {
|
|
10744
|
-
const collection = this._collection(params.collection, account);
|
|
10745
|
-
const values = params.items.map((i) => BigInt(i.value));
|
|
10746
|
-
const tokenUris = params.items.map((i) => i.tokenUri);
|
|
10747
|
-
const call = collection.populate("batch_mint_edition", [
|
|
10748
|
-
params.to,
|
|
10749
|
-
values,
|
|
10750
|
-
tokenUris
|
|
10751
|
-
]);
|
|
10752
|
-
const res = await account.execute([call]);
|
|
10753
|
-
return { txHash: res.transaction_hash };
|
|
10754
|
-
}
|
|
10755
|
-
async addSupply(account, params) {
|
|
10756
|
-
const collection = this._collection(params.collection, account);
|
|
10757
|
-
const call = collection.populate("add_supply", [
|
|
10758
|
-
params.to,
|
|
10759
|
-
BigInt(params.tokenId),
|
|
10760
|
-
BigInt(params.value)
|
|
10761
|
-
]);
|
|
10762
|
-
const res = await account.execute([call]);
|
|
10763
|
-
return { txHash: res.transaction_hash };
|
|
10764
|
-
}
|
|
10765
|
-
async setDefaultRoyalty(account, params) {
|
|
10766
|
-
const collection = this._collection(params.collection, account);
|
|
10767
|
-
const call = collection.populate("set_default_royalty", [
|
|
10768
|
-
params.receiver,
|
|
10769
|
-
BigInt(params.feeNumerator)
|
|
10770
|
-
]);
|
|
10771
|
-
const res = await account.execute([call]);
|
|
10772
|
-
return { txHash: res.transaction_hash };
|
|
10773
|
-
}
|
|
10774
|
-
async setTokenRoyalty(account, params) {
|
|
10775
|
-
const collection = this._collection(params.collection, account);
|
|
10776
|
-
const call = collection.populate("set_token_royalty", [
|
|
10777
|
-
BigInt(params.tokenId),
|
|
10778
|
-
params.receiver,
|
|
10779
|
-
BigInt(params.feeNumerator)
|
|
10780
|
-
]);
|
|
10781
|
-
const res = await account.execute([call]);
|
|
10782
|
-
return { txHash: res.transaction_hash };
|
|
10783
|
-
}
|
|
10784
|
-
async setApprovalForAll(account, params) {
|
|
10785
|
-
const collection = this._collection(params.collection, account);
|
|
10786
|
-
const call = collection.populate("set_approval_for_all", [
|
|
10787
|
-
params.operator,
|
|
10788
|
-
params.approved
|
|
10789
|
-
]);
|
|
10790
|
-
const res = await account.execute([call]);
|
|
10791
|
-
return { txHash: res.transaction_hash };
|
|
10792
|
-
}
|
|
10793
|
-
};
|
|
10794
|
-
|
|
10795
|
-
// src/starknet/services/coinLaunchMath.ts
|
|
10796
|
-
var COIN_DECIMALS = 18;
|
|
10797
|
-
var SUGGESTED_DEFAULT_PRICE = 0.01;
|
|
10798
|
-
var MIN_SUPPLY = 1000n;
|
|
10799
|
-
var MAX_SUPPLY = 1000000000000n;
|
|
10800
|
-
var MAX_FELT_BYTES = 31;
|
|
10801
|
-
function byteLen(s) {
|
|
10802
|
-
return new TextEncoder().encode(s).length;
|
|
10803
|
-
}
|
|
10804
|
-
function validateName(s) {
|
|
10805
|
-
if (!s.trim()) return "Name is required";
|
|
10806
|
-
if (byteLen(s) > MAX_FELT_BYTES) return `Name must be at most ${MAX_FELT_BYTES} bytes`;
|
|
10807
|
-
return null;
|
|
10808
|
-
}
|
|
10809
|
-
function validateSymbol(s) {
|
|
10810
|
-
if (!s.trim()) return "Symbol is required";
|
|
10811
|
-
if (byteLen(s) > MAX_FELT_BYTES) return `Symbol must be at most ${MAX_FELT_BYTES} bytes`;
|
|
10812
|
-
return null;
|
|
10813
|
-
}
|
|
10814
|
-
function validateSupply(human) {
|
|
10815
|
-
if (!/^\d+$/.test(human.trim())) return "Supply must be a whole number";
|
|
10816
|
-
const v = BigInt(human.trim());
|
|
10817
|
-
if (v < MIN_SUPPLY) return `Supply must be at least ${MIN_SUPPLY.toString()}`;
|
|
10818
|
-
if (v > MAX_SUPPLY) return `Supply must be at most ${MAX_SUPPLY.toString()}`;
|
|
10819
|
-
return null;
|
|
10820
|
-
}
|
|
10821
|
-
function toRaw(human, decimals = COIN_DECIMALS) {
|
|
10822
|
-
return human * 10n ** BigInt(decimals);
|
|
10823
|
-
}
|
|
10824
|
-
function teamCoinsRaw(supplyRaw, pct) {
|
|
10825
|
-
const bps = BigInt(Math.round(pct * 100));
|
|
10826
|
-
return supplyRaw * bps / 10000n;
|
|
10827
|
-
}
|
|
10828
|
-
var PRICE_SCALE = 1000000000000n;
|
|
10829
|
-
function buybackQuoteRaw(teamCoinsRawValue, price, quoteDecimals) {
|
|
10830
|
-
const priceScaled = BigInt(Math.round(price * Number(PRICE_SCALE)));
|
|
10831
|
-
return teamCoinsRawValue * priceScaled * 10n ** BigInt(quoteDecimals) / (PRICE_SCALE * 10n ** BigInt(COIN_DECIMALS));
|
|
10832
|
-
}
|
|
10833
|
-
function fdvHuman(supplyHuman, price) {
|
|
10834
|
-
return supplyHuman * price;
|
|
10835
|
-
}
|
|
10836
|
-
|
|
10837
|
-
// src/starknet/services/creatorCoin.ts
|
|
10838
|
-
var VALIDATED_EKUBO_PARAMS = {
|
|
10839
|
-
fee: "0xc49ba5e353f7d00000000000000000",
|
|
10840
|
-
tickSpacing: 5982n,
|
|
10841
|
-
startingPrice: { mag: 4600158n, sign: true },
|
|
10842
|
-
bound: 88719042n
|
|
10843
|
-
};
|
|
10844
|
-
var TICK_BASE = 1.000001;
|
|
10845
|
-
function priceToEkuboParams(quoteDecimals, price = SUGGESTED_DEFAULT_PRICE) {
|
|
10846
|
-
const decAdj = 10 ** (COIN_DECIMALS - quoteDecimals);
|
|
10847
|
-
const rawRatio = price / decAdj;
|
|
10848
|
-
const tickSpacing = Number(VALIDATED_EKUBO_PARAMS.tickSpacing);
|
|
10849
|
-
const rawTick = Math.log(rawRatio) / Math.log(TICK_BASE);
|
|
10850
|
-
const roundedTick = Math.trunc(rawTick / tickSpacing) * tickSpacing;
|
|
10851
|
-
return {
|
|
10852
|
-
fee: VALIDATED_EKUBO_PARAMS.fee,
|
|
10853
|
-
tickSpacing: VALIDATED_EKUBO_PARAMS.tickSpacing,
|
|
10854
|
-
startingPrice: { mag: BigInt(Math.abs(roundedTick)), sign: roundedTick < 0 },
|
|
10855
|
-
bound: VALIDATED_EKUBO_PARAMS.bound
|
|
10856
|
-
};
|
|
10857
|
-
}
|
|
10858
|
-
function validatePrice(quoteDecimals, price) {
|
|
10859
|
-
if (!isFinite(price) || price <= 0) return "Price must be a positive number";
|
|
10860
|
-
const decAdj = 10 ** (COIN_DECIMALS - quoteDecimals);
|
|
10861
|
-
const rawRatio = price / decAdj;
|
|
10862
|
-
if (!isFinite(rawRatio) || rawRatio <= 0) return "Price must be a positive number";
|
|
10863
|
-
const rawTick = Math.log(rawRatio) / Math.log(TICK_BASE);
|
|
10864
|
-
if (!isFinite(rawTick)) return "Price is outside the supported range";
|
|
10865
|
-
const bound = Number(VALIDATED_EKUBO_PARAMS.bound);
|
|
10866
|
-
if (Math.abs(rawTick) >= bound) return "Price is outside the supported range";
|
|
10867
|
-
return null;
|
|
10868
|
-
}
|
|
10869
|
-
var MAX_TEAM_ALLOCATION_PERCENT = 10;
|
|
10870
|
-
var MAX_HOLDERS_AT_LAUNCH = 10;
|
|
10871
|
-
function u2562(parts, offset = 0) {
|
|
10872
|
-
return BigInt(parts[offset] ?? "0x0") + (BigInt(parts[offset + 1] ?? "0x0") << 128n);
|
|
10873
|
-
}
|
|
10874
|
-
async function getCreatorCoinGuarantees(coinAddress, provider) {
|
|
10875
|
-
const call = (entrypoint) => provider.callContract({ contractAddress: coinAddress, entrypoint, calldata: [] });
|
|
10876
|
-
const [launchedRes, allocRes] = await Promise.all([
|
|
10877
|
-
call("is_launched").catch(() => null),
|
|
10878
|
-
call("get_team_allocation").catch(() => null)
|
|
10879
|
-
]);
|
|
10880
|
-
if (!launchedRes || !allocRes) return null;
|
|
10881
|
-
const [supplyRes, blockRes, liquidityRes] = await Promise.all([
|
|
10882
|
-
call("total_supply"),
|
|
10883
|
-
call("launched_at_block_number").catch(() => null),
|
|
10884
|
-
call("liquidity_type").catch(() => null)
|
|
10885
|
-
]);
|
|
10886
|
-
const isLaunched = BigInt(launchedRes[0] ?? "0x0") !== 0n;
|
|
10887
|
-
const totalSupply = u2562(supplyRes);
|
|
10888
|
-
const teamAllocation = u2562(allocRes);
|
|
10889
|
-
const teamAllocationPercent = totalSupply > 0n ? Number(teamAllocation * 10000n / totalSupply) / 100 : null;
|
|
10890
|
-
const launchedAtBlock = isLaunched && blockRes?.[0] != null ? Number(BigInt(blockRes[0])) : null;
|
|
10891
|
-
const liquidityPositionId = liquidityRes && BigInt(liquidityRes[0] ?? "0x1") === 0n && liquidityRes[2] != null ? BigInt(liquidityRes[2]).toString() : null;
|
|
10892
|
-
return {
|
|
10893
|
-
isLaunched,
|
|
10894
|
-
launchedAtBlock,
|
|
10895
|
-
totalSupplyRaw: totalSupply.toString(),
|
|
10896
|
-
teamAllocationRaw: teamAllocation.toString(),
|
|
10897
|
-
teamAllocationPercent,
|
|
10898
|
-
liquidityPositionId
|
|
10899
|
-
};
|
|
10900
|
-
}
|
|
10901
|
-
var _factoryContract = null;
|
|
10902
|
-
function factoryContract() {
|
|
10903
|
-
if (!_factoryContract) {
|
|
10904
|
-
_factoryContract = newContract(
|
|
10905
|
-
CreatorCoinFactoryABI,
|
|
10906
|
-
getStarknetCoordinates("STARKNET").creatorCoinFactory
|
|
10907
|
-
);
|
|
10908
|
-
}
|
|
10909
|
-
return _factoryContract;
|
|
10910
|
-
}
|
|
10911
|
-
function buildCreateCreatorCoinCall(params) {
|
|
10912
|
-
const salt = params.salt ?? BigInt("0x" + Date.now().toString(16));
|
|
10913
|
-
return factoryContract().populate("create_creator_coin", [
|
|
10914
|
-
params.owner,
|
|
10915
|
-
params.name,
|
|
10916
|
-
params.symbol,
|
|
10917
|
-
BigInt(params.initialSupply),
|
|
10918
|
-
BigInt(salt)
|
|
10919
|
-
]);
|
|
10920
|
-
}
|
|
10921
|
-
function buildLaunchOnEkuboCalls(params) {
|
|
10922
|
-
const ek = params.ekubo;
|
|
10923
|
-
const launchParameters = {
|
|
10924
|
-
creator_coin_address: params.creatorCoin,
|
|
10925
|
-
transfer_restriction_delay: params.transferRestrictionDelay ?? 0,
|
|
10926
|
-
max_percentage_buy_launch: params.maxPercentageBuyLaunch ?? 200,
|
|
10927
|
-
quote_address: params.quoteToken,
|
|
10928
|
-
initial_holders: params.initialHolders,
|
|
10929
|
-
initial_holders_amounts: params.initialHoldersAmounts.map((a) => BigInt(a))
|
|
10930
|
-
};
|
|
10931
|
-
const ekuboParameters = {
|
|
10932
|
-
fee: BigInt(ek.fee),
|
|
10933
|
-
tick_spacing: BigInt(ek.tickSpacing),
|
|
10934
|
-
starting_price: { mag: BigInt(ek.startingPrice.mag), sign: ek.startingPrice.sign },
|
|
10935
|
-
bound: BigInt(ek.bound)
|
|
10936
|
-
};
|
|
10937
|
-
const calls = [];
|
|
10938
|
-
if (params.quoteFundAmount !== void 0) {
|
|
10939
|
-
const amt = uint256.bnToUint256(BigInt(params.quoteFundAmount));
|
|
10940
|
-
calls.push({
|
|
10941
|
-
contractAddress: params.quoteToken,
|
|
10942
|
-
entrypoint: "transfer",
|
|
10943
|
-
calldata: [getStarknetCoordinates("STARKNET").creatorCoinFactory, amt.low, amt.high]
|
|
10944
|
-
});
|
|
10945
|
-
}
|
|
10946
|
-
calls.push(factoryContract().populate("launch_on_ekubo", [launchParameters, ekuboParameters]));
|
|
10947
|
-
return calls;
|
|
10948
|
-
}
|
|
10949
|
-
var CREATOR_COIN_CREATED_SELECTOR = hash.getSelectorFromName("CreatorCoinCreated");
|
|
10950
|
-
function parseCreatorCoinCreated(receipt) {
|
|
10951
|
-
const factory = normalizeAddress("STARKNET", getStarknetCoordinates("STARKNET").creatorCoinFactory);
|
|
10952
|
-
for (const ev of receipt?.events ?? []) {
|
|
10953
|
-
let from;
|
|
10954
|
-
try {
|
|
10955
|
-
from = normalizeAddress("STARKNET", ev.from_address ?? "");
|
|
10956
|
-
} catch {
|
|
10957
|
-
continue;
|
|
10958
|
-
}
|
|
10959
|
-
if (from !== factory) continue;
|
|
10960
|
-
const k0 = ev.keys?.[0];
|
|
10961
|
-
if (!k0 || normalizeAddress("STARKNET", k0) !== normalizeAddress("STARKNET", CREATOR_COIN_CREATED_SELECTOR)) continue;
|
|
10962
|
-
const data = ev.data ?? [];
|
|
10963
|
-
if (data.length < 1) continue;
|
|
10964
|
-
return normalizeAddress("STARKNET", data[data.length - 1]);
|
|
10965
|
-
}
|
|
10966
|
-
throw new Error("Coin deployed but the coin address could not be read from the receipt");
|
|
10967
|
-
}
|
|
10968
|
-
var CreatorCoinService = class {
|
|
10969
|
-
constructor(config) {
|
|
10970
|
-
this.factoryAddress = getStarknetCoordinates(config.chain).creatorCoinFactory;
|
|
10971
|
-
}
|
|
10972
|
-
_factory(account) {
|
|
10973
|
-
return newContract(CreatorCoinFactoryABI, this.factoryAddress, account);
|
|
10974
|
-
}
|
|
10975
|
-
async createCreatorCoin(account, params) {
|
|
10976
|
-
const res = await account.execute([buildCreateCreatorCoinCall(params)]);
|
|
10977
|
-
return { txHash: res.transaction_hash };
|
|
10978
|
-
}
|
|
10979
|
-
async launchOnEkubo(account, params) {
|
|
10980
|
-
const res = await account.execute(buildLaunchOnEkuboCalls(params));
|
|
10981
|
-
return { txHash: res.transaction_hash };
|
|
10982
|
-
}
|
|
10983
|
-
async isCreatorCoin(address, account) {
|
|
10984
|
-
const r = await this._factory(account).is_creator_coin(address);
|
|
10985
|
-
return BigInt(r) === 1n;
|
|
10986
|
-
}
|
|
10987
|
-
};
|
|
10988
|
-
var TicketService = class {
|
|
10989
|
-
constructor(config) {
|
|
10990
|
-
this.factoryAddress = getStarknetCoordinates(config.chain).ipTicketsFactory;
|
|
10991
|
-
}
|
|
10992
|
-
_factory(account, factoryAddress) {
|
|
10993
|
-
const address = factoryAddress ?? this.factoryAddress;
|
|
10994
|
-
if (!address) throw new Error("IP-Tickets factory address not configured for this chain");
|
|
10995
|
-
return newContract(IPTicketCollectionFactoryABI, normalizeAddress("STARKNET", address), account);
|
|
10996
|
-
}
|
|
10997
|
-
_collection(address, account) {
|
|
10998
|
-
return newContract(IPTicketCollectionABI, normalizeAddress("STARKNET", address), account);
|
|
10999
|
-
}
|
|
11000
|
-
async deployCollection(account, params) {
|
|
11001
|
-
const call = this._factory(account, params.factoryAddress).populate("deploy_collection", [
|
|
11002
|
-
params.name,
|
|
11003
|
-
params.symbol,
|
|
11004
|
-
params.baseUri
|
|
11005
|
-
]);
|
|
11006
|
-
const res = await account.execute([call]);
|
|
11007
|
-
return { txHash: res.transaction_hash };
|
|
11008
|
-
}
|
|
11009
|
-
async createTicket(account, params) {
|
|
11010
|
-
const startTime = params.startTime != null ? new CairoOption(CairoOptionVariant.Some, params.startTime) : new CairoOption(CairoOptionVariant.None);
|
|
11011
|
-
const endTime = params.endTime != null ? new CairoOption(CairoOptionVariant.Some, params.endTime) : new CairoOption(CairoOptionVariant.None);
|
|
11012
|
-
const call = this._collection(params.collection, account).populate("create_ticket", [
|
|
11013
|
-
cairo.uint256(params.maxSupply),
|
|
11014
|
-
startTime,
|
|
11015
|
-
endTime,
|
|
11016
|
-
params.royaltyBps,
|
|
11017
|
-
params.metadataUri
|
|
11018
|
-
]);
|
|
11019
|
-
const res = await account.execute([call]);
|
|
11020
|
-
return { txHash: res.transaction_hash };
|
|
11021
|
-
}
|
|
11022
|
-
async mint(account, params) {
|
|
11023
|
-
const call = this._collection(params.collection, account).populate("mint", [
|
|
11024
|
-
params.to,
|
|
11025
|
-
cairo.uint256(params.tokenId),
|
|
11026
|
-
cairo.uint256(params.amount)
|
|
11027
|
-
]);
|
|
11028
|
-
const res = await account.execute([call]);
|
|
11029
|
-
return { txHash: res.transaction_hash };
|
|
11030
|
-
}
|
|
11031
|
-
};
|
|
11032
|
-
var ClubService = class {
|
|
11033
|
-
constructor(config) {
|
|
11034
|
-
this.factoryAddress = getStarknetCoordinates(config.chain).ipClubFactory;
|
|
11035
|
-
}
|
|
11036
|
-
_factory(account, factoryAddress) {
|
|
11037
|
-
const address = factoryAddress ?? this.factoryAddress;
|
|
11038
|
-
if (!address) throw new Error("IP-Club factory address not configured for this chain");
|
|
11039
|
-
return newContract(IPClubFactoryABI, normalizeAddress("STARKNET", address), account);
|
|
11040
|
-
}
|
|
11041
|
-
_collection(address, account) {
|
|
11042
|
-
return newContract(IPClubCollectionABI, normalizeAddress("STARKNET", address), account);
|
|
11043
|
-
}
|
|
11044
|
-
async deployCollection(account, params) {
|
|
11045
|
-
const call = this._factory(account, params.factoryAddress).populate("deploy_collection", [
|
|
11046
|
-
params.name,
|
|
11047
|
-
params.symbol,
|
|
11048
|
-
params.baseUri
|
|
11049
|
-
]);
|
|
11050
|
-
const res = await account.execute([call]);
|
|
11051
|
-
return { txHash: res.transaction_hash };
|
|
11052
|
-
}
|
|
11053
|
-
async createMembership(account, params) {
|
|
11054
|
-
const startTime = params.startTime != null ? new CairoOption(CairoOptionVariant.Some, params.startTime) : new CairoOption(CairoOptionVariant.None);
|
|
11055
|
-
const endTime = params.endTime != null ? new CairoOption(CairoOptionVariant.Some, params.endTime) : new CairoOption(CairoOptionVariant.None);
|
|
11056
|
-
const call = this._collection(params.collection, account).populate("create_membership", [
|
|
11057
|
-
cairo.uint256(params.maxSupply),
|
|
11058
|
-
startTime,
|
|
11059
|
-
endTime,
|
|
11060
|
-
params.royaltyBps,
|
|
11061
|
-
params.metadataUri
|
|
11062
|
-
]);
|
|
11063
|
-
const res = await account.execute([call]);
|
|
11064
|
-
return { txHash: res.transaction_hash };
|
|
11065
|
-
}
|
|
11066
|
-
async mint(account, params) {
|
|
11067
|
-
const call = this._collection(params.collection, account).populate("mint", [
|
|
11068
|
-
params.to,
|
|
11069
|
-
cairo.uint256(params.tokenId),
|
|
11070
|
-
cairo.uint256(params.amount)
|
|
11071
|
-
]);
|
|
11072
|
-
const res = await account.execute([call]);
|
|
11073
|
-
return { txHash: res.transaction_hash };
|
|
11074
|
-
}
|
|
11075
|
-
};
|
|
11076
|
-
var SponsorshipService = class {
|
|
11077
|
-
constructor(config) {
|
|
11078
|
-
this.sponsorshipAddress = getStarknetCoordinates(config.chain).ipSponsorship;
|
|
11079
|
-
}
|
|
11080
|
-
_contract(account, address) {
|
|
11081
|
-
const resolved = address ?? this.sponsorshipAddress;
|
|
11082
|
-
if (!resolved) {
|
|
11083
|
-
throw new Error("IP-Sponsorship address not configured for this chain");
|
|
11084
|
-
}
|
|
11085
|
-
return newContract(IPSponsorshipABI, normalizeAddress("STARKNET", resolved), account);
|
|
11086
|
-
}
|
|
11087
|
-
async createOffer(account, params) {
|
|
11088
|
-
const specificSponsor = params.specificSponsor ? new CairoOption(CairoOptionVariant.Some, params.specificSponsor) : new CairoOption(CairoOptionVariant.None);
|
|
11089
|
-
const call = this._contract(account, params.sponsorshipAddress).populate("create_offer", [
|
|
11090
|
-
params.nftContract,
|
|
11091
|
-
cairo.uint256(params.tokenId),
|
|
11092
|
-
cairo.uint256(params.minAmount),
|
|
11093
|
-
params.duration,
|
|
11094
|
-
params.paymentToken,
|
|
11095
|
-
params.licenseTermsUri,
|
|
11096
|
-
params.transferable,
|
|
11097
|
-
cairo.uint256(params.royaltyBps),
|
|
11098
|
-
specificSponsor
|
|
11099
|
-
]);
|
|
11100
|
-
const res = await account.execute([call]);
|
|
11101
|
-
return { txHash: res.transaction_hash };
|
|
11102
|
-
}
|
|
11103
|
-
async setOfferOpen(account, params) {
|
|
11104
|
-
const call = this._contract(account, params.sponsorshipAddress).populate("set_offer_open", [
|
|
11105
|
-
cairo.uint256(params.offerId),
|
|
11106
|
-
params.open
|
|
11107
|
-
]);
|
|
11108
|
-
const res = await account.execute([call]);
|
|
11109
|
-
return { txHash: res.transaction_hash };
|
|
11110
|
-
}
|
|
11111
|
-
async placeBid(account, params) {
|
|
11112
|
-
const sponsorshipAddress = params.sponsorshipAddress ?? this.sponsorshipAddress;
|
|
11113
|
-
if (!sponsorshipAddress) {
|
|
11114
|
-
throw new Error("IP-Sponsorship address not configured for this chain");
|
|
11115
|
-
}
|
|
11116
|
-
const amount = cairo.uint256(params.amount);
|
|
11117
|
-
const approveCall = {
|
|
11118
|
-
contractAddress: params.paymentToken,
|
|
11119
|
-
entrypoint: "approve",
|
|
11120
|
-
calldata: [normalizeAddress("STARKNET", sponsorshipAddress), amount.low.toString(), amount.high.toString()]
|
|
11121
|
-
};
|
|
11122
|
-
const bidCall = this._contract(account, sponsorshipAddress).populate("place_bid", [
|
|
11123
|
-
cairo.uint256(params.offerId),
|
|
11124
|
-
amount
|
|
11125
|
-
]);
|
|
11126
|
-
const res = await account.execute([approveCall, bidCall]);
|
|
11127
|
-
return { txHash: res.transaction_hash };
|
|
11128
|
-
}
|
|
11129
|
-
async retractBid(account, params) {
|
|
11130
|
-
const call = this._contract(account, params.sponsorshipAddress).populate("retract_bid", [
|
|
11131
|
-
cairo.uint256(params.offerId)
|
|
11132
|
-
]);
|
|
11133
|
-
const res = await account.execute([call]);
|
|
11134
|
-
return { txHash: res.transaction_hash };
|
|
11135
|
-
}
|
|
11136
|
-
async acceptBid(account, params) {
|
|
11137
|
-
const call = this._contract(account, params.sponsorshipAddress).populate("accept_bid", [
|
|
11138
|
-
cairo.uint256(params.offerId),
|
|
11139
|
-
params.sponsor
|
|
11140
|
-
]);
|
|
11141
|
-
const res = await account.execute([call]);
|
|
11142
|
-
return { txHash: res.transaction_hash };
|
|
11143
|
-
}
|
|
11144
|
-
async proposeSponsorship(account, params) {
|
|
11145
|
-
const call = this._contract(account, params.sponsorshipAddress).populate("propose_sponsorship", [
|
|
11146
|
-
params.nftContract,
|
|
11147
|
-
cairo.uint256(params.tokenId),
|
|
11148
|
-
cairo.uint256(params.amount),
|
|
11149
|
-
params.duration,
|
|
11150
|
-
params.validUntil ?? 0,
|
|
11151
|
-
params.paymentToken,
|
|
11152
|
-
params.licenseTermsUri,
|
|
11153
|
-
params.transferable,
|
|
11154
|
-
cairo.uint256(params.royaltyBps)
|
|
11155
|
-
]);
|
|
11156
|
-
const res = await account.execute([call]);
|
|
11157
|
-
return { txHash: res.transaction_hash };
|
|
11158
|
-
}
|
|
11159
|
-
async withdrawProposal(account, params) {
|
|
11160
|
-
const call = this._contract(account, params.sponsorshipAddress).populate("withdraw_proposal", [
|
|
11161
|
-
cairo.uint256(params.proposalId)
|
|
11162
|
-
]);
|
|
11163
|
-
const res = await account.execute([call]);
|
|
11164
|
-
return { txHash: res.transaction_hash };
|
|
11165
|
-
}
|
|
11166
|
-
async acceptProposal(account, params) {
|
|
11167
|
-
const call = this._contract(account, params.sponsorshipAddress).populate("accept_proposal", [
|
|
11168
|
-
cairo.uint256(params.proposalId)
|
|
11169
|
-
]);
|
|
11170
|
-
const res = await account.execute([call]);
|
|
11171
|
-
return { txHash: res.transaction_hash };
|
|
11172
|
-
}
|
|
11173
|
-
async rejectProposal(account, params) {
|
|
11174
|
-
const call = this._contract(account, params.sponsorshipAddress).populate("reject_proposal", [
|
|
11175
|
-
cairo.uint256(params.proposalId)
|
|
11176
|
-
]);
|
|
11177
|
-
const res = await account.execute([call]);
|
|
11178
|
-
return { txHash: res.transaction_hash };
|
|
11179
|
-
}
|
|
11180
|
-
};
|
|
11181
|
-
function createChainProvider(backendUrl, apiKey) {
|
|
11182
|
-
return new RpcProvider({
|
|
11183
|
-
nodeUrl: `${backendUrl.replace(/\/$/, "")}/v1/rpc`,
|
|
11184
|
-
headers: apiKey ? { "x-api-key": apiKey } : {},
|
|
11185
|
-
blockIdentifier: "latest"
|
|
11186
|
-
});
|
|
11187
|
-
}
|
|
11188
|
-
|
|
11189
|
-
// src/starknet/client.ts
|
|
11190
|
-
var MedialaneClient = class {
|
|
11191
|
-
constructor(rawConfig = {}) {
|
|
11192
|
-
this.config = resolveConfig(rawConfig);
|
|
11193
|
-
this.services = {
|
|
11194
|
-
pop: new PopService(this.config),
|
|
11195
|
-
drop: new DropService(this.config),
|
|
11196
|
-
erc1155Collection: new ERC1155CollectionService(this.config),
|
|
11197
|
-
creatorCoin: new CreatorCoinService(this.config),
|
|
11198
|
-
ticket: new TicketService(this.config),
|
|
11199
|
-
club: new ClubService(this.config),
|
|
11200
|
-
sponsorship: new SponsorshipService(this.config)
|
|
11201
|
-
};
|
|
11202
|
-
if (!this.config.backendUrl) {
|
|
11203
|
-
const sentinel = new ApiClient("https://medialane-sdk-no-backend.invalid", this.config.apiKey);
|
|
11204
|
-
const apiMethodNames = new Set(
|
|
11205
|
-
Object.getOwnPropertyNames(ApiClient.prototype).filter(
|
|
11206
|
-
(k) => k !== "constructor" && typeof sentinel[k] === "function"
|
|
11207
|
-
)
|
|
11208
|
-
);
|
|
11209
|
-
this.api = new Proxy(sentinel, {
|
|
11210
|
-
get(target, prop, receiver) {
|
|
11211
|
-
if (typeof prop === "symbol" || !apiMethodNames.has(prop)) {
|
|
11212
|
-
return Reflect.get(target, prop, receiver);
|
|
11213
|
-
}
|
|
11214
|
-
return () => {
|
|
11215
|
-
throw new Error(
|
|
11216
|
-
`backendUrl not configured. Pass backendUrl to MedialaneClient to use .api.${String(prop)}()`
|
|
11217
|
-
);
|
|
11218
|
-
};
|
|
11219
|
-
}
|
|
11220
|
-
});
|
|
11221
|
-
} else {
|
|
11222
|
-
this.api = new ApiClient(this.config.backendUrl, this.config.apiKey, this.config.retryOptions, this.config.chain);
|
|
11223
|
-
}
|
|
11224
|
-
}
|
|
11225
|
-
get chain() {
|
|
11226
|
-
return this.config.chain;
|
|
11227
|
-
}
|
|
11228
|
-
get provider() {
|
|
11229
|
-
if (!this.config.backendUrl) {
|
|
11230
|
-
throw new Error("backendUrl not configured. Pass backendUrl to MedialaneClient to use .provider");
|
|
11231
|
-
}
|
|
11232
|
-
return this._provider ?? (this._provider = createChainProvider(this.config.backendUrl, this.config.apiKey));
|
|
11233
|
-
}
|
|
11234
|
-
get marketplaceContract() {
|
|
11235
|
-
return this.config.marketplaceContract;
|
|
11236
|
-
}
|
|
11237
|
-
};
|
|
11238
|
-
|
|
11239
|
-
// src/starknet/erc20.ts
|
|
11240
|
-
async function erc20Balance(provider, token, holder) {
|
|
11241
|
-
const read = (entrypoint) => provider.callContract({ contractAddress: token, entrypoint, calldata: [holder] }, "latest");
|
|
11242
|
-
const [low = "0x0", high = "0x0"] = await read("balanceOf").catch(() => read("balance_of"));
|
|
11243
|
-
return BigInt(low) + (BigInt(high) << 128n);
|
|
11244
|
-
}
|
|
11245
|
-
var STARKNET_DOMAIN = [
|
|
11246
|
-
{ name: "name", type: "shortstring" },
|
|
11247
|
-
{ name: "version", type: "shortstring" },
|
|
11248
|
-
{ name: "chainId", type: "shortstring" },
|
|
11249
|
-
{ name: "revision", type: "shortstring" }
|
|
11250
|
-
];
|
|
11251
|
-
var OFFER_ITEM = [
|
|
11252
|
-
{ name: "item_type", type: "shortstring" },
|
|
11253
|
-
{ name: "token", type: "ContractAddress" },
|
|
11254
|
-
{ name: "identifier_or_criteria", type: "felt" },
|
|
11255
|
-
{ name: "amount", type: "felt" }
|
|
11256
|
-
];
|
|
11257
|
-
var CONSIDERATION_ITEM = [
|
|
11258
|
-
{ name: "item_type", type: "shortstring" },
|
|
11259
|
-
{ name: "token", type: "ContractAddress" },
|
|
11260
|
-
{ name: "identifier_or_criteria", type: "felt" },
|
|
11261
|
-
{ name: "amount", type: "felt" },
|
|
11262
|
-
{ name: "recipient", type: "ContractAddress" }
|
|
11263
|
-
];
|
|
11264
|
-
var ORDER_PARAMETERS = [
|
|
11265
|
-
{ name: "offerer", type: "ContractAddress" },
|
|
11266
|
-
{ name: "marketplace", type: "ContractAddress" },
|
|
11267
|
-
{ name: "offer", type: "OfferItem" },
|
|
11268
|
-
{ name: "consideration", type: "ConsiderationItem" },
|
|
11269
|
-
{ name: "royalty_max_bps", type: "felt" },
|
|
11270
|
-
{ name: "start_time", type: "felt" },
|
|
11271
|
-
{ name: "end_time", type: "felt" },
|
|
11272
|
-
{ name: "salt", type: "felt" },
|
|
11273
|
-
{ name: "counter", type: "felt" }
|
|
11274
|
-
];
|
|
11275
|
-
var ORDER_CANCELLATION = [
|
|
11276
|
-
{ name: "order_hash", type: "felt" },
|
|
11277
|
-
{ name: "offerer", type: "ContractAddress" }
|
|
11278
|
-
];
|
|
11279
|
-
var DOMAIN_VERSION = {
|
|
11280
|
-
erc721: "5",
|
|
11281
|
-
erc1155: "4"
|
|
11282
|
-
};
|
|
11283
|
-
function buildDomain(standard, chainId) {
|
|
11284
|
-
return {
|
|
11285
|
-
name: "Medialane",
|
|
11286
|
-
version: DOMAIN_VERSION[standard],
|
|
11287
|
-
chainId,
|
|
11288
|
-
revision: TypedDataRevision.ACTIVE
|
|
11289
|
-
};
|
|
11290
|
-
}
|
|
11291
|
-
function buildOrderTypedData(message, chainId) {
|
|
11292
|
-
return {
|
|
11293
|
-
domain: buildDomain("erc721", chainId),
|
|
11294
|
-
primaryType: "OrderParameters",
|
|
11295
|
-
types: {
|
|
11296
|
-
StarknetDomain: STARKNET_DOMAIN,
|
|
11297
|
-
OrderParameters: ORDER_PARAMETERS,
|
|
11298
|
-
OfferItem: OFFER_ITEM,
|
|
11299
|
-
ConsiderationItem: CONSIDERATION_ITEM
|
|
11300
|
-
},
|
|
11301
|
-
message
|
|
11302
|
-
};
|
|
11303
|
-
}
|
|
11304
|
-
function build1155OrderTypedData(message, chainId) {
|
|
11305
|
-
return {
|
|
11306
|
-
domain: buildDomain("erc1155", chainId),
|
|
11307
|
-
primaryType: "OrderParameters",
|
|
11308
|
-
types: {
|
|
11309
|
-
StarknetDomain: STARKNET_DOMAIN,
|
|
11310
|
-
OrderParameters: ORDER_PARAMETERS,
|
|
11311
|
-
OfferItem: OFFER_ITEM,
|
|
11312
|
-
ConsiderationItem: CONSIDERATION_ITEM
|
|
11313
|
-
},
|
|
11314
|
-
message
|
|
11315
|
-
};
|
|
11316
|
-
}
|
|
11317
|
-
function buildCancellationTypedData(message, chainId) {
|
|
11318
|
-
return {
|
|
11319
|
-
domain: buildDomain("erc721", chainId),
|
|
11320
|
-
primaryType: "OrderCancellation",
|
|
11321
|
-
types: {
|
|
11322
|
-
StarknetDomain: STARKNET_DOMAIN,
|
|
11323
|
-
OrderCancellation: ORDER_CANCELLATION
|
|
11324
|
-
},
|
|
11325
|
-
message
|
|
11326
|
-
};
|
|
11327
|
-
}
|
|
11328
|
-
function build1155CancellationTypedData(message, chainId) {
|
|
11329
|
-
return {
|
|
11330
|
-
domain: buildDomain("erc1155", chainId),
|
|
11331
|
-
primaryType: "OrderCancellation",
|
|
11332
|
-
types: {
|
|
11333
|
-
StarknetDomain: STARKNET_DOMAIN,
|
|
11334
|
-
OrderCancellation: ORDER_CANCELLATION
|
|
11335
|
-
},
|
|
11336
|
-
message
|
|
11337
|
-
};
|
|
10502
|
+
function buildFeeCall(p, cfg) {
|
|
10503
|
+
const fee = feeAmount(p.grossAmount, feeBps(p.surface, cfg));
|
|
10504
|
+
if (fee <= 0n) return null;
|
|
10505
|
+
const u = cairo.uint256(fee.toString());
|
|
10506
|
+
return {
|
|
10507
|
+
contractAddress: p.token,
|
|
10508
|
+
entrypoint: "transfer",
|
|
10509
|
+
calldata: [cfg.fundAddress, u.low.toString(), u.high.toString()]
|
|
10510
|
+
};
|
|
11338
10511
|
}
|
|
11339
10512
|
|
|
11340
10513
|
// src/starknet/marketplace/build.ts
|
|
11341
10514
|
function contractFor(cfg) {
|
|
11342
|
-
return newContract(IPMarketplaceABI, cfg.
|
|
10515
|
+
return newContract(IPMarketplaceABI, cfg.marketplace721Contract);
|
|
11343
10516
|
}
|
|
11344
10517
|
function buildListingOrder(i, cfg) {
|
|
11345
10518
|
const orderParams = {
|
|
11346
10519
|
offerer: i.offerer,
|
|
11347
|
-
marketplace: cfg.
|
|
10520
|
+
marketplace: cfg.marketplace721Contract,
|
|
11348
10521
|
offer: { item_type: "ERC721", token: i.nftContract, identifier_or_criteria: i.tokenId, amount: "1" },
|
|
11349
10522
|
consideration: {
|
|
11350
10523
|
item_type: "ERC20",
|
|
@@ -11365,7 +10538,7 @@ function buildListingOrder(i, cfg) {
|
|
|
11365
10538
|
function buildOfferOrder(i, cfg) {
|
|
11366
10539
|
const orderParams = {
|
|
11367
10540
|
offerer: i.offerer,
|
|
11368
|
-
marketplace: cfg.
|
|
10541
|
+
marketplace: cfg.marketplace721Contract,
|
|
11369
10542
|
offer: { item_type: "ERC20", token: i.paymentTokenAddress, identifier_or_criteria: "0", amount: i.priceWei },
|
|
11370
10543
|
consideration: {
|
|
11371
10544
|
item_type: "ERC721",
|
|
@@ -11405,7 +10578,7 @@ function buildFulfillCalls(a, cfg) {
|
|
|
11405
10578
|
const approve = {
|
|
11406
10579
|
contractAddress: a.paymentToken,
|
|
11407
10580
|
entrypoint: "approve",
|
|
11408
|
-
calldata: [cfg.
|
|
10581
|
+
calldata: [cfg.marketplace721Contract, u.low.toString(), u.high.toString()]
|
|
11409
10582
|
};
|
|
11410
10583
|
const fulfill = contractFor(cfg).populate("fulfill_order", [a.orderHash]);
|
|
11411
10584
|
const fee = buildFeeCall(
|
|
@@ -11526,15 +10699,15 @@ var StarknetVenue = class {
|
|
|
11526
10699
|
}
|
|
11527
10700
|
async incrementCounter(signer) {
|
|
11528
10701
|
return signer.execute([
|
|
11529
|
-
{ contractAddress: this.deps.config.
|
|
10702
|
+
{ contractAddress: this.deps.config.marketplace721Contract, entrypoint: "increment_counter", calldata: [] }
|
|
11530
10703
|
]);
|
|
11531
10704
|
}
|
|
11532
10705
|
getOrderDetails(orderRef) {
|
|
11533
|
-
const marketplace = newContract(IPMarketplaceABI, this.deps.config.
|
|
10706
|
+
const marketplace = newContract(IPMarketplaceABI, this.deps.config.marketplace721Contract, this.deps.provider);
|
|
11534
10707
|
return marketplace.get_order_details(orderRef);
|
|
11535
10708
|
}
|
|
11536
10709
|
async getCounter(address) {
|
|
11537
|
-
return this.readCounter(this.deps.config.
|
|
10710
|
+
return this.readCounter(this.deps.config.marketplace721Contract, address);
|
|
11538
10711
|
}
|
|
11539
10712
|
async fulfillOrder(signer, orderRef, opts) {
|
|
11540
10713
|
const o = await this.deps.resolveOrder(orderRef);
|
|
@@ -11557,7 +10730,7 @@ var StarknetVenue = class {
|
|
|
11557
10730
|
const startTime = Math.floor(Date.now() / 1e3) + START_TIME_BUFFER_SECS;
|
|
11558
10731
|
const endTime = p.endTime && p.endTime > 0 ? p.endTime : startTime + NO_EXPIRY_SECONDS;
|
|
11559
10732
|
const quantity = p.quantity ?? "1";
|
|
11560
|
-
const marketplace = standard === "ERC1155" ? this.deps.config.marketplace1155Contract : this.deps.config.
|
|
10733
|
+
const marketplace = standard === "ERC1155" ? this.deps.config.marketplace1155Contract : this.deps.config.marketplace721Contract;
|
|
11561
10734
|
const counter = String(await this.readCounter(marketplace, signer.address));
|
|
11562
10735
|
let typedData;
|
|
11563
10736
|
let buildCalls;
|
|
@@ -11619,7 +10792,7 @@ var StarknetVenue = class {
|
|
|
11619
10792
|
const approve = {
|
|
11620
10793
|
contractAddress: nftContract,
|
|
11621
10794
|
entrypoint: "approve",
|
|
11622
|
-
calldata: [this.deps.config.
|
|
10795
|
+
calldata: [this.deps.config.marketplace721Contract, id.low.toString(), id.high.toString()]
|
|
11623
10796
|
};
|
|
11624
10797
|
let approved = false;
|
|
11625
10798
|
try {
|
|
@@ -11628,7 +10801,7 @@ var StarknetVenue = class {
|
|
|
11628
10801
|
entrypoint: "get_approved",
|
|
11629
10802
|
calldata: [id.low.toString(), id.high.toString()]
|
|
11630
10803
|
});
|
|
11631
|
-
approved = BigInt(res[0]).toString() === BigInt(this.deps.config.
|
|
10804
|
+
approved = BigInt(res[0]).toString() === BigInt(this.deps.config.marketplace721Contract).toString();
|
|
11632
10805
|
} catch {
|
|
11633
10806
|
}
|
|
11634
10807
|
return { approvalNeeded: !approved, approve };
|
|
@@ -11817,13 +10990,7 @@ var FundingTransferNotSentError = class extends Error {
|
|
|
11817
10990
|
}
|
|
11818
10991
|
};
|
|
11819
10992
|
function fundingApiFor(client) {
|
|
11820
|
-
return
|
|
11821
|
-
createFunding: (input) => client.createFunding(input),
|
|
11822
|
-
getFundingChallenge: (id, payer) => client.getFundingChallenge(id, payer),
|
|
11823
|
-
authorizeFunding: (id, input) => client.authorizeFunding(id, input),
|
|
11824
|
-
submitFunding: (id, txHash) => client.submitFunding(id, txHash),
|
|
11825
|
-
cancelFunding: (id) => client.cancelFunding(id)
|
|
11826
|
-
};
|
|
10993
|
+
return client.portal.funding;
|
|
11827
10994
|
}
|
|
11828
10995
|
function buildFundingTransferCall(instructions) {
|
|
11829
10996
|
const amount = BigInt(instructions.amountAtomic);
|
|
@@ -11842,32 +11009,32 @@ async function fundWithChainTransfer(api, wallet, options) {
|
|
|
11842
11009
|
const maxPolls = options.maxPolls ?? 20;
|
|
11843
11010
|
step("creating");
|
|
11844
11011
|
const params = options.amount !== void 0 ? { amount: options.amount } : { amountUsdc: options.amountUsdc };
|
|
11845
|
-
const
|
|
11012
|
+
const intent = await api.create({ method: "chain-transfer", params });
|
|
11846
11013
|
let txHash;
|
|
11847
11014
|
let transferStarted = false;
|
|
11848
11015
|
try {
|
|
11849
11016
|
step("signing");
|
|
11850
|
-
const challenge = await api.
|
|
11851
|
-
const signature = await wallet.signTypedData(challenge.
|
|
11017
|
+
const challenge = await api.challenge(intent.id, wallet.address);
|
|
11018
|
+
const signature = await wallet.signTypedData(challenge.typedData);
|
|
11852
11019
|
step("authorizing");
|
|
11853
|
-
const authorized = await api.
|
|
11020
|
+
const authorized = await api.authorize(intent.id, { payer: wallet.address, signature });
|
|
11854
11021
|
step("paying");
|
|
11855
11022
|
transferStarted = true;
|
|
11856
|
-
({ txHash } = await wallet.sendTransfer(buildFundingTransferCall(authorized.
|
|
11023
|
+
({ txHash } = await wallet.sendTransfer(buildFundingTransferCall(authorized.instructions)));
|
|
11857
11024
|
} catch (err) {
|
|
11858
11025
|
if (!transferStarted || err instanceof FundingTransferNotSentError) {
|
|
11859
|
-
await api.
|
|
11026
|
+
await api.cancel(intent.id).catch(() => void 0);
|
|
11860
11027
|
}
|
|
11861
11028
|
throw err;
|
|
11862
11029
|
}
|
|
11863
11030
|
step("confirming");
|
|
11864
11031
|
let reason = "waiting for the transfer to confirm";
|
|
11865
11032
|
for (let attempt = 0; attempt < maxPolls; attempt++) {
|
|
11866
|
-
const res = await api.
|
|
11867
|
-
if (res.
|
|
11868
|
-
return { status: "SETTLED", intentId: intent.id, credited: res.
|
|
11033
|
+
const res = await api.submit(intent.id, txHash);
|
|
11034
|
+
if (res.status === "SETTLED") {
|
|
11035
|
+
return { status: "SETTLED", intentId: intent.id, credited: res.credited };
|
|
11869
11036
|
}
|
|
11870
|
-
reason = res.
|
|
11037
|
+
reason = res.reason;
|
|
11871
11038
|
await sleep(pollMs);
|
|
11872
11039
|
}
|
|
11873
11040
|
return { status: "PENDING", intentId: intent.id, reason };
|
|
@@ -11875,7 +11042,7 @@ async function fundWithChainTransfer(api, wallet, options) {
|
|
|
11875
11042
|
|
|
11876
11043
|
// src/starknet/services/executeIntent.ts
|
|
11877
11044
|
async function confirmIntentBestEffort(client, intentId, txHash) {
|
|
11878
|
-
await client.api.
|
|
11045
|
+
await client.api.intents.confirm(intentId, txHash).catch(() => {
|
|
11879
11046
|
});
|
|
11880
11047
|
}
|
|
11881
11048
|
var SYNC_TIMEOUT_MS = 2e4;
|
|
@@ -11892,8 +11059,8 @@ async function syncTransactionBestEffort(client, txHash, timeoutMs = SYNC_TIMEOU
|
|
|
11892
11059
|
});
|
|
11893
11060
|
const sync = (async () => {
|
|
11894
11061
|
while (!stopped) {
|
|
11895
|
-
const again = await client.api.syncTransaction(txHash).then(
|
|
11896
|
-
(res) => res
|
|
11062
|
+
const again = await client.api.intents.syncTransaction(txHash).then(
|
|
11063
|
+
(res) => res?.pending === true,
|
|
11897
11064
|
readableLater
|
|
11898
11065
|
);
|
|
11899
11066
|
if (!again || Date.now() + retryMs >= deadline) return;
|
|
@@ -11929,8 +11096,8 @@ async function executeIntent(signer, client, intent, opts = {}) {
|
|
|
11929
11096
|
let calls;
|
|
11930
11097
|
if (intent.requiresSignature) {
|
|
11931
11098
|
const signature = await signer.signTypedData(intent.typedData);
|
|
11932
|
-
const signed = await client.api.
|
|
11933
|
-
calls = signed.
|
|
11099
|
+
const signed = await client.api.intents.submitSignature(intent.id, signature);
|
|
11100
|
+
calls = signed.calls;
|
|
11934
11101
|
} else {
|
|
11935
11102
|
calls = intent.calls;
|
|
11936
11103
|
}
|
|
@@ -11965,727 +11132,584 @@ var DEPLOY_EVENTS = {
|
|
|
11965
11132
|
var IP_MINTED_SELECTOR = BigInt(hash.getSelectorFromName("IPMinted"));
|
|
11966
11133
|
var TRANSFER_SELECTOR = BigInt(hash.getSelectorFromName("Transfer"));
|
|
11967
11134
|
function sameFelt(a, b) {
|
|
11968
|
-
if (a === void 0) return false;
|
|
11969
|
-
try {
|
|
11970
|
-
return BigInt(a) === BigInt(b);
|
|
11971
|
-
} catch {
|
|
11972
|
-
return false;
|
|
11973
|
-
}
|
|
11974
|
-
}
|
|
11975
|
-
function u2563(low, high) {
|
|
11976
|
-
return (BigInt(low ?? 0) + (BigInt(high ?? 0) << 128n)).toString();
|
|
11977
|
-
}
|
|
11978
|
-
function deployedCollectionFromReceipt(receipt, service) {
|
|
11979
|
-
const factory = getService(service)?.onchain?.STARKNET?.factoryAddress;
|
|
11980
|
-
const { event, address } = DEPLOY_EVENTS[service];
|
|
11981
|
-
const selector = BigInt(hash.getSelectorFromName(event));
|
|
11982
|
-
for (const e of receipt.events ?? []) {
|
|
11983
|
-
if (factory && !sameFelt(e.from_address, factory)) continue;
|
|
11984
|
-
if (!sameFelt(e.keys?.[0], selector)) continue;
|
|
11985
|
-
const value = address(e);
|
|
11986
|
-
if (value) return normalizeAddress("STARKNET", value);
|
|
11987
|
-
}
|
|
11988
|
-
return null;
|
|
11989
|
-
}
|
|
11990
|
-
function mintedTokenIdFromReceipt(receipt, contract) {
|
|
11991
|
-
for (const e of receipt.events ?? []) {
|
|
11992
|
-
if (!sameFelt(e.from_address, contract)) continue;
|
|
11993
|
-
const keys = e.keys ?? [];
|
|
11994
|
-
if (sameFelt(keys[0], IP_MINTED_SELECTOR) && keys.length >= 3) return u2563(keys[1], keys[2]);
|
|
11995
|
-
if (sameFelt(keys[0], TRANSFER_SELECTOR) && keys.length === 5 && sameFelt(keys[1], 0n)) return u2563(keys[3], keys[4]);
|
|
11996
|
-
}
|
|
11997
|
-
return null;
|
|
11998
|
-
}
|
|
11999
|
-
|
|
12000
|
-
// src/starknet/services/sponsoredExecutor.ts
|
|
12001
|
-
var SponsoredCallRejectedError = class extends Error {
|
|
12002
|
-
};
|
|
12003
|
-
var FALLBACK_FUNDING_FAILURES = /* @__PURE__ */ new Set(["sponsor_unavailable", "credits_exhausted"]);
|
|
12004
|
-
function allowsFallbackFunding(code, status, stage) {
|
|
12005
|
-
if (code) return FALLBACK_FUNDING_FAILURES.has(code);
|
|
12006
|
-
return stage === "build" ? status >= 500 : status === 503;
|
|
12007
|
-
}
|
|
12008
|
-
async function failureOf(res, fallback) {
|
|
12009
|
-
const body = await res.json().catch(() => null);
|
|
12010
|
-
return { reason: body?.error || fallback, code: typeof body?.code === "string" ? body.code : void 0 };
|
|
12011
|
-
}
|
|
12012
|
-
async function executeSponsored(config, signer, request) {
|
|
12013
|
-
const doFetch = config.fetchImpl ?? fetch;
|
|
12014
|
-
const base = config.proxyUrl.replace(/\/$/, "");
|
|
12015
|
-
const headers = { "Content-Type": "application/json", ...config.headers };
|
|
12016
|
-
const buildRes = await doFetch(`${base}/build`, {
|
|
12017
|
-
method: "POST",
|
|
12018
|
-
headers,
|
|
12019
|
-
body: JSON.stringify(request)
|
|
12020
|
-
});
|
|
12021
|
-
if (!buildRes.ok) {
|
|
12022
|
-
const { reason, code } = await failureOf(buildRes, "We couldn't prepare this transaction.");
|
|
12023
|
-
if (allowsFallbackFunding(code, buildRes.status, "build")) return { status: "unavailable", reason };
|
|
12024
|
-
throw new SponsoredCallRejectedError(reason);
|
|
12025
|
-
}
|
|
12026
|
-
const { typedData } = await buildRes.json();
|
|
12027
|
-
const signature = await signer.signTypedData(typedData);
|
|
12028
|
-
const executeRes = await doFetch(`${base}/execute`, {
|
|
12029
|
-
method: "POST",
|
|
12030
|
-
headers,
|
|
12031
|
-
body: JSON.stringify({ ...request, typedData, signature })
|
|
12032
|
-
});
|
|
12033
|
-
if (!executeRes.ok) {
|
|
12034
|
-
const { reason, code } = await failureOf(executeRes, "We couldn't submit this transaction.");
|
|
12035
|
-
if (allowsFallbackFunding(code, executeRes.status, "execute")) {
|
|
12036
|
-
return { status: "unavailable", reason };
|
|
12037
|
-
}
|
|
12038
|
-
throw new SponsoredCallRejectedError(reason);
|
|
12039
|
-
}
|
|
12040
|
-
const { transactionHash } = await executeRes.json();
|
|
12041
|
-
return { status: "sponsored", transactionHash };
|
|
12042
|
-
}
|
|
12043
|
-
function encodeByteArray(str) {
|
|
12044
|
-
const bytes = new TextEncoder().encode(str);
|
|
12045
|
-
const fullChunks = [];
|
|
12046
|
-
let i = 0;
|
|
12047
|
-
while (i + 31 <= bytes.length) {
|
|
12048
|
-
let val = 0n;
|
|
12049
|
-
for (const b of bytes.slice(i, i + 31)) {
|
|
12050
|
-
val = val << 8n | BigInt(b);
|
|
12051
|
-
}
|
|
12052
|
-
fullChunks.push(num.toHex(val));
|
|
12053
|
-
i += 31;
|
|
12054
|
-
}
|
|
12055
|
-
const remaining = bytes.slice(i);
|
|
12056
|
-
let pendingVal = 0n;
|
|
12057
|
-
for (const b of remaining) {
|
|
12058
|
-
pendingVal = pendingVal << 8n | BigInt(b);
|
|
12059
|
-
}
|
|
12060
|
-
return [
|
|
12061
|
-
fullChunks.length.toString(),
|
|
12062
|
-
...fullChunks,
|
|
12063
|
-
num.toHex(pendingVal),
|
|
12064
|
-
remaining.length.toString()
|
|
12065
|
-
];
|
|
12066
|
-
}
|
|
12067
|
-
var STARK_ORDER = 3618502788666131213697322783095070105526743751716087489154079457884512865583n;
|
|
12068
|
-
function deriveOwnerKeyPair(secret, recipientId) {
|
|
12069
|
-
const prk = extract(sha256, secret);
|
|
12070
|
-
const okm = expand(sha256, prk, new TextEncoder().encode(recipientId), 32);
|
|
12071
|
-
let scalar = BigInt("0x" + Buffer.from(okm).toString("hex")) % STARK_ORDER;
|
|
12072
|
-
if (scalar === 0n) scalar = 1n;
|
|
12073
|
-
const privateKey = num.toHex(scalar);
|
|
12074
|
-
const publicKey = ec.starkCurve.getStarkKey(privateKey);
|
|
12075
|
-
return { privateKey, publicKey };
|
|
12076
|
-
}
|
|
12077
|
-
var STARKNET_SIGNER_TYPE = "0x537461726b6e6574205369676e6572";
|
|
12078
|
-
var OPTION_NONE = "0x1";
|
|
12079
|
-
var SIGNER_STARKNET = "0x0";
|
|
12080
|
-
function computeOwnerGuid(ownerPubkey) {
|
|
12081
|
-
return hash.computePoseidonHash(STARKNET_SIGNER_TYPE, num.toHex(ownerPubkey));
|
|
11135
|
+
if (a === void 0) return false;
|
|
11136
|
+
try {
|
|
11137
|
+
return BigInt(a) === BigInt(b);
|
|
11138
|
+
} catch {
|
|
11139
|
+
return false;
|
|
11140
|
+
}
|
|
12082
11141
|
}
|
|
12083
|
-
function
|
|
12084
|
-
return
|
|
12085
|
-
contractAddress: accountAddress,
|
|
12086
|
-
entrypoint: "change_owners",
|
|
12087
|
-
calldata: [
|
|
12088
|
-
num.toHex(guidsToRemove.length),
|
|
12089
|
-
...guidsToRemove,
|
|
12090
|
-
num.toHex(pubkeysToAdd.length),
|
|
12091
|
-
...pubkeysToAdd.flatMap((p) => [SIGNER_STARKNET, num.toHex(p)]),
|
|
12092
|
-
OPTION_NONE
|
|
12093
|
-
]
|
|
12094
|
-
};
|
|
11142
|
+
function u256(low, high) {
|
|
11143
|
+
return (BigInt(low ?? 0) + (BigInt(high ?? 0) << 128n)).toString();
|
|
12095
11144
|
}
|
|
12096
|
-
function
|
|
12097
|
-
|
|
11145
|
+
function deployedCollectionFromReceipt(receipt, service) {
|
|
11146
|
+
const factory = getService(service)?.onchain?.STARKNET?.factoryAddress;
|
|
11147
|
+
const { event, address } = DEPLOY_EVENTS[service];
|
|
11148
|
+
const selector = BigInt(hash.getSelectorFromName(event));
|
|
11149
|
+
for (const e of receipt.events ?? []) {
|
|
11150
|
+
if (factory && !sameFelt(e.from_address, factory)) continue;
|
|
11151
|
+
if (!sameFelt(e.keys?.[0], selector)) continue;
|
|
11152
|
+
const value = address(e);
|
|
11153
|
+
if (value) return normalizeAddress("STARKNET", value);
|
|
11154
|
+
}
|
|
11155
|
+
return null;
|
|
12098
11156
|
}
|
|
12099
|
-
function
|
|
12100
|
-
|
|
11157
|
+
function mintedTokenIdFromReceipt(receipt, contract) {
|
|
11158
|
+
for (const e of receipt.events ?? []) {
|
|
11159
|
+
if (!sameFelt(e.from_address, contract)) continue;
|
|
11160
|
+
const keys = e.keys ?? [];
|
|
11161
|
+
if (sameFelt(keys[0], IP_MINTED_SELECTOR) && keys.length >= 3) return u256(keys[1], keys[2]);
|
|
11162
|
+
if (sameFelt(keys[0], TRANSFER_SELECTOR) && keys.length === 5 && sameFelt(keys[1], 0n)) return u256(keys[3], keys[4]);
|
|
11163
|
+
}
|
|
11164
|
+
return null;
|
|
12101
11165
|
}
|
|
12102
|
-
|
|
12103
|
-
|
|
11166
|
+
var FRAGMENT_KEY = "pop-proof";
|
|
11167
|
+
var toHex = (x) => "0x" + x.toString(16).padStart(64, "0");
|
|
11168
|
+
var poseidon = (xs) => BigInt(hash.computePoseidonHashOnElements(xs.map((x) => "0x" + x.toString(16))));
|
|
11169
|
+
var nodeHash = (a, b) => a < b ? poseidon([a, b]) : poseidon([b, a]);
|
|
11170
|
+
function popLeafHash(address) {
|
|
11171
|
+
return poseidon([poseidon([BigInt(address)])]);
|
|
12104
11172
|
}
|
|
12105
|
-
function
|
|
11173
|
+
function merkleTree(leafHashes) {
|
|
11174
|
+
const leaves = [...leafHashes].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
11175
|
+
const tree = new Array(2 * leaves.length - 1);
|
|
11176
|
+
leaves.forEach((leaf, i) => tree[tree.length - 1 - i] = leaf);
|
|
11177
|
+
for (let i = tree.length - 1 - leaves.length; i >= 0; i--) {
|
|
11178
|
+
tree[i] = nodeHash(tree[2 * i + 1], tree[2 * i + 2]);
|
|
11179
|
+
}
|
|
12106
11180
|
return {
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
11181
|
+
root: tree[0],
|
|
11182
|
+
proof(leaf) {
|
|
11183
|
+
let i = tree.lastIndexOf(leaf);
|
|
11184
|
+
if (i < tree.length - leaves.length) throw new Error("Not a leaf of this tree");
|
|
11185
|
+
const proof = [];
|
|
11186
|
+
while (i > 0) {
|
|
11187
|
+
proof.push(tree[i % 2 === 1 ? i + 1 : i - 1]);
|
|
11188
|
+
i = Math.floor((i - 1) / 2);
|
|
11189
|
+
}
|
|
11190
|
+
return proof;
|
|
11191
|
+
}
|
|
12111
11192
|
};
|
|
12112
11193
|
}
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
}
|
|
12121
|
-
function encodeStarknetSignerArray(pubkeys) {
|
|
12122
|
-
return [num.toHex(pubkeys.length), ...pubkeys.flatMap(encodeStarknetSigner)];
|
|
11194
|
+
function buildPopAllowlist(addresses) {
|
|
11195
|
+
const unique = [...new Set(addresses.map((a) => normalizeAddress("STARKNET", a)))];
|
|
11196
|
+
if (unique.length === 0) throw new Error("An allowlist needs at least one address");
|
|
11197
|
+
const leaves = unique.map((address) => ({ address, leaf: popLeafHash(address) }));
|
|
11198
|
+
const tree = merkleTree(leaves.map((l) => l.leaf));
|
|
11199
|
+
const proofs = {};
|
|
11200
|
+
for (const { address, leaf } of leaves) proofs[address] = tree.proof(leaf).map(toHex);
|
|
11201
|
+
return { root: toHex(tree.root), proofs };
|
|
12123
11202
|
}
|
|
12124
|
-
function
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
calldata: [...encodeFeltArray([]), ...encodeStarknetSignerArray([guardianPubkey])]
|
|
12129
|
-
};
|
|
11203
|
+
function verifyPopProof(root, address, proof) {
|
|
11204
|
+
let computed = popLeafHash(address);
|
|
11205
|
+
for (const sibling of proof) computed = nodeHash(computed, BigInt(sibling));
|
|
11206
|
+
return computed === BigInt(root);
|
|
12130
11207
|
}
|
|
12131
|
-
function
|
|
12132
|
-
return {
|
|
12133
|
-
contractAddress: norm(targetAddress),
|
|
12134
|
-
entrypoint: "trigger_escape_owner",
|
|
12135
|
-
calldata: encodeStarknetSigner(newOwnerPubkey)
|
|
12136
|
-
};
|
|
11208
|
+
function encodePopClaimFragment(proof) {
|
|
11209
|
+
return `#${FRAGMENT_KEY}=${proof.join(",")}`;
|
|
12137
11210
|
}
|
|
12138
|
-
function
|
|
12139
|
-
|
|
11211
|
+
function decodePopClaimFragment(fragment) {
|
|
11212
|
+
const raw = new URLSearchParams(fragment.replace(/^#/, "")).get(FRAGMENT_KEY);
|
|
11213
|
+
if (raw === null) return null;
|
|
11214
|
+
if (raw === "") return [];
|
|
11215
|
+
const parts = raw.split(",");
|
|
11216
|
+
return parts.every((p) => /^0x[0-9a-fA-F]{1,64}$/.test(p)) ? parts : null;
|
|
12140
11217
|
}
|
|
12141
|
-
function
|
|
12142
|
-
|
|
11218
|
+
function popClaimLinks(origin, collection, list) {
|
|
11219
|
+
const base = `${origin}${collectionHref("STARKNET", collection)}`;
|
|
11220
|
+
return Object.entries(list.proofs).map(([address, proof]) => ({
|
|
11221
|
+
address,
|
|
11222
|
+
url: `${base}${encodePopClaimFragment(proof)}`
|
|
11223
|
+
}));
|
|
12143
11224
|
}
|
|
12144
|
-
function
|
|
12145
|
-
|
|
12146
|
-
const out = [];
|
|
12147
|
-
for (let i = 0; i < len; i++) {
|
|
12148
|
-
const base = 1 + i * 3;
|
|
12149
|
-
out.push({
|
|
12150
|
-
type: SIGNER_TYPE_NAMES[Number(res[base])] ?? "Starknet",
|
|
12151
|
-
guid: res[base + 1],
|
|
12152
|
-
storedValue: res[base + 2]
|
|
12153
|
-
});
|
|
12154
|
-
}
|
|
12155
|
-
return out;
|
|
11225
|
+
function popClaimLinksCsv(links) {
|
|
11226
|
+
return ["address,claim_link", ...links.map((l) => `${l.address},${l.url}`)].join("\n");
|
|
12156
11227
|
}
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
const status = ESCAPE_STATUS_NAMES[Number(res[statusIndex])] ?? "None";
|
|
12165
|
-
return { readyAt, escapeType, status };
|
|
11228
|
+
async function popClaimInfo(provider, collection) {
|
|
11229
|
+
const contractAddress = normalizeAddress("STARKNET", collection);
|
|
11230
|
+
const [root, end] = await Promise.all([
|
|
11231
|
+
provider.callContract({ contractAddress, entrypoint: "allowlist_root", calldata: [] }),
|
|
11232
|
+
provider.callContract({ contractAddress, entrypoint: "claim_end_time", calldata: [] })
|
|
11233
|
+
]);
|
|
11234
|
+
return { root: root[0] ?? "0x0", claimEndTime: Number(BigInt(end[0] ?? "0x0")) };
|
|
12166
11235
|
}
|
|
12167
|
-
|
|
12168
|
-
const
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
|
|
12172
|
-
|
|
12173
|
-
|
|
11236
|
+
function popClaimState(input) {
|
|
11237
|
+
const { hasClaimed, proof, wallet, info } = input;
|
|
11238
|
+
if (hasClaimed === true) return "claimed";
|
|
11239
|
+
if (hasClaimed === null || info === null) return "loading";
|
|
11240
|
+
if (BigInt(info.root) === 0n) return "closed";
|
|
11241
|
+
if (info.claimEndTime !== 0 && info.now > info.claimEndTime) return "ended";
|
|
11242
|
+
if (proof === null) return "no-link";
|
|
11243
|
+
if (!wallet || !verifyPopProof(info.root, wallet, proof)) return "wrong-wallet";
|
|
11244
|
+
return "ready";
|
|
12174
11245
|
}
|
|
12175
|
-
|
|
11246
|
+
var addr = (a) => normalizeAddress("STARKNET", a);
|
|
11247
|
+
var byteArrayFelts = (s) => CallData.compile([byteArray.byteArrayFromString(s)]);
|
|
11248
|
+
var popCalls = {
|
|
11249
|
+
claim(collection, proof) {
|
|
11250
|
+
return { contractAddress: addr(collection), entrypoint: "claim", calldata: [String(proof.length), ...proof] };
|
|
11251
|
+
},
|
|
11252
|
+
/** An empty `tokenUri` uses the collection's URI. */
|
|
11253
|
+
issue(collection, recipient, tokenUri = "") {
|
|
11254
|
+
return { contractAddress: addr(collection), entrypoint: "issue", calldata: [addr(recipient), ...byteArrayFelts(tokenUri)] };
|
|
11255
|
+
},
|
|
11256
|
+
/** Only the token's holder can burn it. */
|
|
11257
|
+
burn(collection, tokenId) {
|
|
11258
|
+
const id = cairo.uint256(BigInt(tokenId));
|
|
11259
|
+
return { contractAddress: addr(collection), entrypoint: "burn", calldata: [String(id.low), String(id.high)] };
|
|
11260
|
+
},
|
|
11261
|
+
setAllowlistRoot(collection, root) {
|
|
11262
|
+
return { contractAddress: addr(collection), entrypoint: "set_allowlist_root", calldata: [root] };
|
|
11263
|
+
}
|
|
11264
|
+
};
|
|
11265
|
+
async function popHasClaimed(provider, collection, address) {
|
|
12176
11266
|
const res = await provider.callContract({
|
|
12177
|
-
contractAddress:
|
|
12178
|
-
entrypoint: "
|
|
12179
|
-
calldata: []
|
|
11267
|
+
contractAddress: normalizeAddress("STARKNET", collection),
|
|
11268
|
+
entrypoint: "has_claimed",
|
|
11269
|
+
calldata: [normalizeAddress("STARKNET", address)]
|
|
12180
11270
|
});
|
|
12181
|
-
return
|
|
11271
|
+
return BigInt(res[0] ?? "0x0") !== 0n;
|
|
12182
11272
|
}
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12188
|
-
|
|
12189
|
-
return
|
|
11273
|
+
var DROP_MAX_CLAIM_QUANTITY = 50n;
|
|
11274
|
+
var addr2 = (a) => normalizeAddress("STARKNET", a);
|
|
11275
|
+
var factoryData = new CallData(DropFactoryABI);
|
|
11276
|
+
var collectionData = new CallData(DropCollectionABI);
|
|
11277
|
+
function toContractTerms(t) {
|
|
11278
|
+
const price = BigInt(t.price);
|
|
11279
|
+
return {
|
|
11280
|
+
start_time: t.startTime,
|
|
11281
|
+
end_time: t.endTime,
|
|
11282
|
+
price: cairo.uint256(price),
|
|
11283
|
+
payment_token: price === 0n ? "0x0" : addr2(t.paymentToken),
|
|
11284
|
+
max_per_wallet: cairo.uint256(BigInt(t.maxPerWallet))
|
|
11285
|
+
};
|
|
12190
11286
|
}
|
|
12191
|
-
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
11287
|
+
var dropCalls = {
|
|
11288
|
+
create(factory, p) {
|
|
11289
|
+
return {
|
|
11290
|
+
contractAddress: addr2(factory),
|
|
11291
|
+
entrypoint: "create_drop",
|
|
11292
|
+
calldata: factoryData.compile("create_drop", {
|
|
11293
|
+
name: p.name,
|
|
11294
|
+
symbol: p.symbol,
|
|
11295
|
+
base_uri: p.baseUri,
|
|
11296
|
+
max_supply: cairo.uint256(BigInt(p.maxSupply)),
|
|
11297
|
+
terms: toContractTerms(p.terms),
|
|
11298
|
+
allowlist_root: p.allowlistRoot ?? "0x0"
|
|
11299
|
+
})
|
|
11300
|
+
};
|
|
11301
|
+
},
|
|
11302
|
+
/** Approve (paid drops) and claim. The platform fee call is added by the caller. */
|
|
11303
|
+
claim(collection, p) {
|
|
11304
|
+
const quantity = BigInt(p.quantity);
|
|
11305
|
+
if (quantity < 1n || quantity > DROP_MAX_CLAIM_QUANTITY) throw new RangeError(`quantity must be 1 to ${DROP_MAX_CLAIM_QUANTITY}`);
|
|
11306
|
+
const total = BigInt(p.price) * quantity;
|
|
11307
|
+
const calls = [];
|
|
11308
|
+
if (total > 0n) {
|
|
11309
|
+
calls.push({
|
|
11310
|
+
contractAddress: addr2(p.paymentToken),
|
|
11311
|
+
entrypoint: "approve",
|
|
11312
|
+
calldata: CallData.compile([addr2(collection), cairo.uint256(total)])
|
|
11313
|
+
});
|
|
11314
|
+
}
|
|
11315
|
+
calls.push({
|
|
11316
|
+
contractAddress: addr2(collection),
|
|
11317
|
+
entrypoint: "claim",
|
|
11318
|
+
calldata: collectionData.compile("claim", { quantity: cairo.uint256(quantity), proof: p.proof ?? [] })
|
|
11319
|
+
});
|
|
11320
|
+
return calls;
|
|
11321
|
+
},
|
|
11322
|
+
/** Organizer only: free mint within the supply cap. */
|
|
11323
|
+
issue(collection, recipient, quantity) {
|
|
11324
|
+
const q = BigInt(quantity);
|
|
11325
|
+
if (q < 1n) throw new RangeError("quantity must be at least 1");
|
|
11326
|
+
return {
|
|
11327
|
+
contractAddress: addr2(collection),
|
|
11328
|
+
entrypoint: "issue",
|
|
11329
|
+
calldata: collectionData.compile("issue", { recipient: addr2(recipient), quantity: cairo.uint256(q) })
|
|
11330
|
+
};
|
|
11331
|
+
},
|
|
11332
|
+
/** Organizer only. 0 opens the drop to everyone. */
|
|
11333
|
+
setAllowlistRoot(collection, root) {
|
|
11334
|
+
return { contractAddress: addr2(collection), entrypoint: "set_allowlist_root", calldata: collectionData.compile("set_allowlist_root", { root }) };
|
|
11335
|
+
}
|
|
11336
|
+
};
|
|
11337
|
+
function dropMintCost(price, quantity, feeBps2) {
|
|
11338
|
+
const subtotal = BigInt(price) * BigInt(quantity);
|
|
11339
|
+
const fee = feeAmount(subtotal, feeBps2);
|
|
11340
|
+
return { subtotal, fee, total: subtotal + fee };
|
|
12198
11341
|
}
|
|
12199
11342
|
|
|
12200
|
-
// src/
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
11343
|
+
// src/starknet/drop-state.ts
|
|
11344
|
+
var hex = (v) => normalizeAddress("STARKNET", v ?? "0x0");
|
|
11345
|
+
var u2562 = (low, high) => BigInt(low ?? "0x0") + (BigInt(high ?? "0x0") << 128n);
|
|
11346
|
+
async function readDrop(provider, collection) {
|
|
11347
|
+
const contractAddress = hex(collection);
|
|
11348
|
+
const read = (entrypoint) => provider.callContract({ contractAddress, entrypoint, calldata: [] });
|
|
11349
|
+
const [organizer, terms, root, max, minted] = await Promise.all([
|
|
11350
|
+
read("organizer"),
|
|
11351
|
+
read("terms"),
|
|
11352
|
+
read("allowlist_root"),
|
|
11353
|
+
read("max_supply"),
|
|
11354
|
+
read("total_minted")
|
|
11355
|
+
]);
|
|
12207
11356
|
return {
|
|
12208
|
-
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
loadAddress() {
|
|
12218
|
-
return this.load()?.address ?? null;
|
|
12219
|
-
},
|
|
12220
|
-
save(sealed) {
|
|
12221
|
-
const previous = this.load();
|
|
12222
|
-
if (previous && previous.address !== sealed.address) {
|
|
12223
|
-
localStorage.setItem(`${storeKey}:${previous.address}`, JSON.stringify(previous));
|
|
12224
|
-
}
|
|
12225
|
-
localStorage.setItem(storeKey, JSON.stringify(sealed));
|
|
12226
|
-
announce();
|
|
12227
|
-
},
|
|
12228
|
-
clear() {
|
|
12229
|
-
localStorage.removeItem(storeKey);
|
|
12230
|
-
announce();
|
|
12231
|
-
},
|
|
12232
|
-
notifyChange: announce,
|
|
12233
|
-
onChange(listener) {
|
|
12234
|
-
window.addEventListener(changeEvent, listener);
|
|
12235
|
-
return () => window.removeEventListener(changeEvent, listener);
|
|
12236
|
-
}
|
|
11357
|
+
organizer: hex(organizer[0]),
|
|
11358
|
+
startTime: Number(BigInt(terms[0] ?? "0x0")),
|
|
11359
|
+
endTime: Number(BigInt(terms[1] ?? "0x0")),
|
|
11360
|
+
price: u2562(terms[2], terms[3]),
|
|
11361
|
+
paymentToken: hex(terms[4]),
|
|
11362
|
+
maxPerWallet: u2562(terms[5], terms[6]),
|
|
11363
|
+
allowlistRoot: root[0] ?? "0x0",
|
|
11364
|
+
maxSupply: u2562(max[0], max[1]),
|
|
11365
|
+
totalMinted: u2562(minted[0], minted[1])
|
|
12237
11366
|
};
|
|
12238
11367
|
}
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
|
|
12243
|
-
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
11368
|
+
async function buildDropClaimCalls(provider, collection, input, feeConfig) {
|
|
11369
|
+
const drop = await readDrop(provider, collection);
|
|
11370
|
+
const calls = dropCalls.claim(collection, {
|
|
11371
|
+
quantity: input.quantity,
|
|
11372
|
+
proof: input.proof,
|
|
11373
|
+
price: drop.price,
|
|
11374
|
+
paymentToken: drop.paymentToken
|
|
11375
|
+
});
|
|
11376
|
+
if (drop.price === 0n) return calls;
|
|
11377
|
+
const fee = buildFeeCall(
|
|
11378
|
+
{ surface: "launchpad", token: drop.paymentToken, grossAmount: drop.price * BigInt(input.quantity) },
|
|
11379
|
+
feeConfig
|
|
11380
|
+
);
|
|
11381
|
+
return fee ? [...calls, fee] : calls;
|
|
11382
|
+
}
|
|
11383
|
+
async function dropClaimedBy(provider, collection, wallet) {
|
|
11384
|
+
const res = await provider.callContract({ contractAddress: hex(collection), entrypoint: "claimed_by", calldata: [hex(wallet)] });
|
|
11385
|
+
return u2562(res[0], res[1]);
|
|
11386
|
+
}
|
|
11387
|
+
function dropMintState(input) {
|
|
11388
|
+
const none = (state) => ({ state, maxQuantity: 0n });
|
|
11389
|
+
const { drop, wallet, claimed, proof, balance, now } = input;
|
|
11390
|
+
if (!drop) return none("loading");
|
|
11391
|
+
if (drop.startTime !== 0 && now < drop.startTime) return none("upcoming");
|
|
11392
|
+
if (drop.endTime !== 0 && now > drop.endTime) return none("ended");
|
|
11393
|
+
const supplyLeft = drop.maxSupply === 0n ? null : drop.maxSupply - drop.totalMinted;
|
|
11394
|
+
if (supplyLeft !== null && supplyLeft <= 0n) return none("sold-out");
|
|
11395
|
+
if (!wallet) return none("no-wallet");
|
|
11396
|
+
if (BigInt(drop.allowlistRoot) !== 0n) {
|
|
11397
|
+
if (proof === null) return none("no-link");
|
|
11398
|
+
if (!verifyPopProof(drop.allowlistRoot, wallet, proof)) return none("not-on-list");
|
|
12254
11399
|
}
|
|
12255
|
-
|
|
12256
|
-
|
|
12257
|
-
|
|
11400
|
+
if (claimed === null) return none("loading");
|
|
11401
|
+
const walletLeft = drop.maxPerWallet === 0n ? null : drop.maxPerWallet - claimed;
|
|
11402
|
+
if (walletLeft !== null && walletLeft <= 0n) return none("limit-reached");
|
|
11403
|
+
let max = DROP_MAX_CLAIM_QUANTITY;
|
|
11404
|
+
if (supplyLeft !== null && supplyLeft < max) max = supplyLeft;
|
|
11405
|
+
if (walletLeft !== null && walletLeft < max) max = walletLeft;
|
|
11406
|
+
if (drop.price > 0n) {
|
|
11407
|
+
if (balance === null) return none("loading");
|
|
11408
|
+
while (max > 0n && dropMintCost(drop.price, max, input.feeBps).total > balance) max--;
|
|
11409
|
+
if (max === 0n) return none("insufficient-balance");
|
|
12258
11410
|
}
|
|
12259
|
-
return
|
|
12260
|
-
}
|
|
12261
|
-
function sanitiseLabel(input) {
|
|
12262
|
-
const raw = typeof input === "string" ? input : "";
|
|
12263
|
-
return raw.replace(/\s+/g, " ").trim().slice(0, LABEL_MAX);
|
|
12264
|
-
}
|
|
12265
|
-
function encodePairingPayload(payload) {
|
|
12266
|
-
return JSON.stringify({
|
|
12267
|
-
scheme: SCHEME,
|
|
12268
|
-
version: VERSION,
|
|
12269
|
-
publicKey: normalisePublicKey(payload.publicKey),
|
|
12270
|
-
label: sanitiseLabel(payload.label)
|
|
12271
|
-
});
|
|
11411
|
+
return { state: "ready", maxQuantity: max };
|
|
12272
11412
|
}
|
|
12273
|
-
function
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12278
|
-
|
|
12279
|
-
}
|
|
12280
|
-
if (data === null || typeof data !== "object") throw new InvalidPairingPayloadError();
|
|
12281
|
-
if (data.scheme !== SCHEME || data.version !== VERSION) throw new InvalidPairingPayloadError();
|
|
12282
|
-
return {
|
|
12283
|
-
publicKey: normalisePublicKey(data.publicKey),
|
|
12284
|
-
label: sanitiseLabel(data.label)
|
|
12285
|
-
};
|
|
11413
|
+
function dropClaimLinks(origin, collection, list) {
|
|
11414
|
+
const base = `${origin}${dropHref(collection)}`;
|
|
11415
|
+
return Object.entries(list.proofs).map(([address, proof]) => ({
|
|
11416
|
+
address,
|
|
11417
|
+
url: `${base}${encodePopClaimFragment(proof)}`
|
|
11418
|
+
}));
|
|
12286
11419
|
}
|
|
12287
|
-
function
|
|
12288
|
-
|
|
12289
|
-
if (!/^0x[0-9a-fA-F]{50,64}$/.test(trimmed)) {
|
|
12290
|
-
throw new InvalidPairingPayloadError("That does not look like an account address.");
|
|
12291
|
-
}
|
|
12292
|
-
if (BigInt(trimmed) === 0n) {
|
|
12293
|
-
throw new InvalidPairingPayloadError("That does not look like an account address.");
|
|
12294
|
-
}
|
|
12295
|
-
return trimmed;
|
|
11420
|
+
function populateCall(abi, contractAddress, entrypoint, args) {
|
|
11421
|
+
return { contractAddress, entrypoint, calldata: new CallData(abi).compile(entrypoint, args) };
|
|
12296
11422
|
}
|
|
12297
|
-
|
|
12298
|
-
|
|
12299
|
-
var
|
|
12300
|
-
var
|
|
12301
|
-
|
|
12302
|
-
constructor(message = "This is not a valid recovery key.") {
|
|
12303
|
-
super(message);
|
|
12304
|
-
this.name = "InvalidRecoveryKeyError";
|
|
12305
|
-
}
|
|
11423
|
+
var addr3 = (address) => normalizeAddress("STARKNET", address);
|
|
11424
|
+
var optionOf = (value) => value != null ? new CairoOption(CairoOptionVariant.Some, value) : new CairoOption(CairoOptionVariant.None);
|
|
11425
|
+
var deployCollectionCall = (abi, factory, p) => populateCall(abi, addr3(factory), "deploy_collection", [p.name, p.symbol, p.baseUri]);
|
|
11426
|
+
var popFactoryCalls = {
|
|
11427
|
+
createCollection: (factory, p) => populateCall(POPFactoryABI, factory, "create_collection", [p.name, p.symbol, p.baseUri, p.claimEndTime])
|
|
12306
11428
|
};
|
|
12307
|
-
var
|
|
12308
|
-
|
|
12309
|
-
|
|
12310
|
-
|
|
12311
|
-
|
|
12312
|
-
|
|
12313
|
-
|
|
11429
|
+
var ticketCalls = {
|
|
11430
|
+
deployCollection: (factory, p) => deployCollectionCall(IPTicketCollectionFactoryABI, factory, p),
|
|
11431
|
+
createTicket: (p) => populateCall(IPTicketCollectionABI, addr3(p.collection), "create_ticket", [
|
|
11432
|
+
cairo.uint256(p.maxSupply),
|
|
11433
|
+
optionOf(p.startTime),
|
|
11434
|
+
optionOf(p.endTime),
|
|
11435
|
+
p.royaltyBps,
|
|
11436
|
+
p.metadataUri
|
|
11437
|
+
]),
|
|
11438
|
+
mint: (p) => populateCall(IPTicketCollectionABI, addr3(p.collection), "mint", [
|
|
11439
|
+
p.to,
|
|
11440
|
+
cairo.uint256(p.tokenId),
|
|
11441
|
+
cairo.uint256(p.amount)
|
|
11442
|
+
])
|
|
11443
|
+
};
|
|
11444
|
+
var clubCalls = {
|
|
11445
|
+
deployCollection: (factory, p) => deployCollectionCall(IPClubFactoryABI, factory, p),
|
|
11446
|
+
createMembership: (p) => populateCall(IPClubCollectionABI, addr3(p.collection), "create_membership", [
|
|
11447
|
+
cairo.uint256(p.maxSupply),
|
|
11448
|
+
optionOf(p.startTime),
|
|
11449
|
+
optionOf(p.endTime),
|
|
11450
|
+
p.royaltyBps,
|
|
11451
|
+
p.metadataUri
|
|
11452
|
+
]),
|
|
11453
|
+
mint: (p) => populateCall(IPClubCollectionABI, addr3(p.collection), "mint", [
|
|
11454
|
+
p.to,
|
|
11455
|
+
cairo.uint256(p.tokenId),
|
|
11456
|
+
cairo.uint256(p.amount)
|
|
11457
|
+
])
|
|
11458
|
+
};
|
|
11459
|
+
var sponsorship = (contract, entrypoint, args) => populateCall(IPSponsorshipABI, addr3(contract), entrypoint, args);
|
|
11460
|
+
var sponsorshipCalls = {
|
|
11461
|
+
createOffer: (contract, p) => sponsorship(contract, "create_offer", [
|
|
11462
|
+
p.nftContract,
|
|
11463
|
+
cairo.uint256(p.tokenId),
|
|
11464
|
+
cairo.uint256(p.minAmount),
|
|
11465
|
+
p.duration,
|
|
11466
|
+
p.paymentToken,
|
|
11467
|
+
p.licenseTermsUri,
|
|
11468
|
+
p.transferable,
|
|
11469
|
+
cairo.uint256(p.royaltyBps),
|
|
11470
|
+
p.specificSponsor ? new CairoOption(CairoOptionVariant.Some, p.specificSponsor) : new CairoOption(CairoOptionVariant.None)
|
|
11471
|
+
]),
|
|
11472
|
+
setOfferOpen: (contract, p) => sponsorship(contract, "set_offer_open", [cairo.uint256(p.offerId), p.open]),
|
|
11473
|
+
placeBid: (contract, p) => {
|
|
11474
|
+
const amount = cairo.uint256(p.amount);
|
|
11475
|
+
return [
|
|
11476
|
+
{
|
|
11477
|
+
contractAddress: p.paymentToken,
|
|
11478
|
+
entrypoint: "approve",
|
|
11479
|
+
calldata: [addr3(contract), amount.low.toString(), amount.high.toString()]
|
|
11480
|
+
},
|
|
11481
|
+
sponsorship(contract, "place_bid", [cairo.uint256(p.offerId), amount])
|
|
11482
|
+
];
|
|
11483
|
+
},
|
|
11484
|
+
retractBid: (contract, p) => sponsorship(contract, "retract_bid", [cairo.uint256(p.offerId)]),
|
|
11485
|
+
acceptBid: (contract, p) => sponsorship(contract, "accept_bid", [cairo.uint256(p.offerId), p.sponsor]),
|
|
11486
|
+
propose: (contract, p) => sponsorship(contract, "propose_sponsorship", [
|
|
11487
|
+
p.nftContract,
|
|
11488
|
+
cairo.uint256(p.tokenId),
|
|
11489
|
+
cairo.uint256(p.amount),
|
|
11490
|
+
p.duration,
|
|
11491
|
+
p.validUntil ?? 0,
|
|
11492
|
+
p.paymentToken,
|
|
11493
|
+
p.licenseTermsUri,
|
|
11494
|
+
p.transferable,
|
|
11495
|
+
cairo.uint256(p.royaltyBps)
|
|
11496
|
+
]),
|
|
11497
|
+
withdrawProposal: (contract, p) => sponsorship(contract, "withdraw_proposal", [cairo.uint256(p.proposalId)]),
|
|
11498
|
+
acceptProposal: (contract, p) => sponsorship(contract, "accept_proposal", [cairo.uint256(p.proposalId)]),
|
|
11499
|
+
rejectProposal: (contract, p) => sponsorship(contract, "reject_proposal", [cairo.uint256(p.proposalId)])
|
|
11500
|
+
};
|
|
11501
|
+
var edition = (collection, entrypoint, args) => populateCall(IPCollection1155ABI, addr3(collection), entrypoint, args);
|
|
11502
|
+
var editionCalls = {
|
|
11503
|
+
deployCollection: (factory, p) => deployCollectionCall(IPCollection1155FactoryABI, factory, p),
|
|
11504
|
+
mintEdition: (p) => edition(p.collection, "mint_edition", [p.to, BigInt(p.value), p.tokenUri]),
|
|
11505
|
+
batchMintEdition: (p) => edition(p.collection, "batch_mint_edition", [
|
|
11506
|
+
p.to,
|
|
11507
|
+
p.items.map((i) => BigInt(i.value)),
|
|
11508
|
+
p.items.map((i) => i.tokenUri)
|
|
11509
|
+
]),
|
|
11510
|
+
addSupply: (p) => edition(p.collection, "add_supply", [p.to, BigInt(p.tokenId), BigInt(p.value)]),
|
|
11511
|
+
setDefaultRoyalty: (p) => edition(p.collection, "set_default_royalty", [p.receiver, BigInt(p.feeNumerator)]),
|
|
11512
|
+
setTokenRoyalty: (p) => edition(p.collection, "set_token_royalty", [BigInt(p.tokenId), p.receiver, BigInt(p.feeNumerator)]),
|
|
11513
|
+
setApprovalForAll: (p) => edition(p.collection, "set_approval_for_all", [p.operator, p.approved])
|
|
11514
|
+
};
|
|
11515
|
+
|
|
11516
|
+
// src/starknet/services/coinLaunchMath.ts
|
|
11517
|
+
var COIN_DECIMALS = 18;
|
|
11518
|
+
var SUGGESTED_DEFAULT_PRICE = 0.01;
|
|
11519
|
+
var MIN_SUPPLY = 1000n;
|
|
11520
|
+
var MAX_SUPPLY = 1000000000000n;
|
|
11521
|
+
var MAX_FELT_BYTES = 31;
|
|
11522
|
+
function byteLen(s) {
|
|
11523
|
+
return new TextEncoder().encode(s).length;
|
|
12314
11524
|
}
|
|
12315
|
-
function
|
|
12316
|
-
if (!
|
|
12317
|
-
return
|
|
11525
|
+
function validateName(s) {
|
|
11526
|
+
if (!s.trim()) return "Name is required";
|
|
11527
|
+
if (byteLen(s) > MAX_FELT_BYTES) return `Name must be at most ${MAX_FELT_BYTES} bytes`;
|
|
11528
|
+
return null;
|
|
12318
11529
|
}
|
|
12319
|
-
function
|
|
12320
|
-
|
|
12321
|
-
if (
|
|
12322
|
-
|
|
12323
|
-
return { walletAddress: computeAccountAddress(publicKeyHex, 0), privateKey: privateKeyHex };
|
|
12324
|
-
}
|
|
12325
|
-
const parts = trimmed.slice(PREFIX.length).split(":");
|
|
12326
|
-
const [walletAddress, privateKey] = parts;
|
|
12327
|
-
if (parts.length !== 2 || !walletAddress || !privateKey || !ADDRESS.test(walletAddress) || BigInt(walletAddress) === 0n) {
|
|
12328
|
-
throw new InvalidRecoveryKeyError();
|
|
12329
|
-
}
|
|
12330
|
-
return { walletAddress: canonicalAddress(walletAddress), privateKey: keyPair(privateKey).privateKeyHex };
|
|
11530
|
+
function validateSymbol(s) {
|
|
11531
|
+
if (!s.trim()) return "Symbol is required";
|
|
11532
|
+
if (byteLen(s) > MAX_FELT_BYTES) return `Symbol must be at most ${MAX_FELT_BYTES} bytes`;
|
|
11533
|
+
return null;
|
|
12331
11534
|
}
|
|
12332
|
-
|
|
12333
|
-
|
|
12334
|
-
|
|
12335
|
-
if (
|
|
12336
|
-
return
|
|
11535
|
+
function validateSupply(human) {
|
|
11536
|
+
if (!/^\d+$/.test(human.trim())) return "Supply must be a whole number";
|
|
11537
|
+
const v = BigInt(human.trim());
|
|
11538
|
+
if (v < MIN_SUPPLY) return `Supply must be at least ${MIN_SUPPLY.toString()}`;
|
|
11539
|
+
if (v > MAX_SUPPLY) return `Supply must be at most ${MAX_SUPPLY.toString()}`;
|
|
11540
|
+
return null;
|
|
12337
11541
|
}
|
|
12338
|
-
function
|
|
12339
|
-
|
|
12340
|
-
if (escape.status === "Ready") return "complete";
|
|
12341
|
-
if (escape.status === "Expired") return "start";
|
|
12342
|
-
return "none";
|
|
11542
|
+
function toRaw(human, decimals = COIN_DECIMALS) {
|
|
11543
|
+
return human * 10n ** BigInt(decimals);
|
|
12343
11544
|
}
|
|
12344
|
-
function
|
|
12345
|
-
|
|
11545
|
+
function teamCoinsRaw(supplyRaw, pct) {
|
|
11546
|
+
const bps = BigInt(Math.round(pct * 100));
|
|
11547
|
+
return supplyRaw * bps / 10000n;
|
|
12346
11548
|
}
|
|
12347
|
-
|
|
12348
|
-
|
|
12349
|
-
|
|
12350
|
-
|
|
12351
|
-
} catch {
|
|
12352
|
-
return false;
|
|
12353
|
-
}
|
|
11549
|
+
var PRICE_SCALE = 1000000000000n;
|
|
11550
|
+
function buybackQuoteRaw(teamCoinsRawValue, price, quoteDecimals) {
|
|
11551
|
+
const priceScaled = BigInt(Math.round(price * Number(PRICE_SCALE)));
|
|
11552
|
+
return teamCoinsRawValue * priceScaled * 10n ** BigInt(quoteDecimals) / (PRICE_SCALE * 10n ** BigInt(COIN_DECIMALS));
|
|
12354
11553
|
}
|
|
12355
|
-
|
|
12356
|
-
|
|
12357
|
-
try {
|
|
12358
|
-
await provider.getClassHashAt(normalizeWalletAddress(address));
|
|
12359
|
-
return true;
|
|
12360
|
-
} catch (err) {
|
|
12361
|
-
if (err?.code === CONTRACT_NOT_FOUND) return false;
|
|
12362
|
-
throw err;
|
|
12363
|
-
}
|
|
11554
|
+
function fdvHuman(supplyHuman, price) {
|
|
11555
|
+
return supplyHuman * price;
|
|
12364
11556
|
}
|
|
12365
11557
|
|
|
12366
|
-
// src/
|
|
12367
|
-
|
|
12368
|
-
|
|
11558
|
+
// src/starknet/services/creatorCoin.ts
|
|
11559
|
+
var VALIDATED_EKUBO_PARAMS = {
|
|
11560
|
+
fee: "0xc49ba5e353f7d00000000000000000",
|
|
11561
|
+
tickSpacing: 5982n,
|
|
11562
|
+
startingPrice: { mag: 4600158n, sign: true },
|
|
11563
|
+
bound: 88719042n
|
|
11564
|
+
};
|
|
11565
|
+
var TICK_BASE = 1.000001;
|
|
11566
|
+
function priceToEkuboParams(quoteDecimals, price = SUGGESTED_DEFAULT_PRICE) {
|
|
11567
|
+
const decAdj = 10 ** (COIN_DECIMALS - quoteDecimals);
|
|
11568
|
+
const rawRatio = price / decAdj;
|
|
11569
|
+
const tickSpacing = Number(VALIDATED_EKUBO_PARAMS.tickSpacing);
|
|
11570
|
+
const rawTick = Math.log(rawRatio) / Math.log(TICK_BASE);
|
|
11571
|
+
const roundedTick = Math.trunc(rawTick / tickSpacing) * tickSpacing;
|
|
12369
11572
|
return {
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
},
|
|
12373
|
-
|
|
12374
|
-
if (!handler) return false;
|
|
12375
|
-
const feeEstimate = address && calls ? estimateFee(address, calls).catch(() => null) : Promise.resolve(null);
|
|
12376
|
-
return handler(feeEstimate);
|
|
12377
|
-
}
|
|
11573
|
+
fee: VALIDATED_EKUBO_PARAMS.fee,
|
|
11574
|
+
tickSpacing: VALIDATED_EKUBO_PARAMS.tickSpacing,
|
|
11575
|
+
startingPrice: { mag: BigInt(Math.abs(roundedTick)), sign: roundedTick < 0 },
|
|
11576
|
+
bound: VALIDATED_EKUBO_PARAMS.bound
|
|
12378
11577
|
};
|
|
12379
11578
|
}
|
|
12380
|
-
function
|
|
12381
|
-
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
const
|
|
12386
|
-
|
|
12387
|
-
|
|
12388
|
-
|
|
12389
|
-
|
|
12390
|
-
const token = getTokenBySymbol(unit === "FRI" ? "STRK" : "ETH");
|
|
12391
|
-
if (!token) throw new Error(`No fee token for unit ${unit}`);
|
|
12392
|
-
return erc20Balance(provider, token.address, address);
|
|
11579
|
+
function validatePrice(quoteDecimals, price) {
|
|
11580
|
+
if (!isFinite(price) || price <= 0) return "Price must be a positive number";
|
|
11581
|
+
const decAdj = 10 ** (COIN_DECIMALS - quoteDecimals);
|
|
11582
|
+
const rawRatio = price / decAdj;
|
|
11583
|
+
if (!isFinite(rawRatio) || rawRatio <= 0) return "Price must be a positive number";
|
|
11584
|
+
const rawTick = Math.log(rawRatio) / Math.log(TICK_BASE);
|
|
11585
|
+
if (!isFinite(rawTick)) return "Price is outside the supported range";
|
|
11586
|
+
const bound = Number(VALIDATED_EKUBO_PARAMS.bound);
|
|
11587
|
+
if (Math.abs(rawTick) >= bound) return "Price is outside the supported range";
|
|
11588
|
+
return null;
|
|
12393
11589
|
}
|
|
12394
|
-
|
|
12395
|
-
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
const { transaction_hash } = await account.execute(calls);
|
|
12399
|
-
return { transactionHash: transaction_hash };
|
|
12400
|
-
}
|
|
12401
|
-
};
|
|
11590
|
+
var MAX_TEAM_ALLOCATION_PERCENT = 10;
|
|
11591
|
+
var MAX_HOLDERS_AT_LAUNCH = 10;
|
|
11592
|
+
function u2563(parts, offset = 0) {
|
|
11593
|
+
return BigInt(parts[offset] ?? "0x0") + (BigInt(parts[offset + 1] ?? "0x0") << 128n);
|
|
12402
11594
|
}
|
|
12403
|
-
function
|
|
12404
|
-
const
|
|
11595
|
+
async function getCreatorCoinGuarantees(coinAddress, provider) {
|
|
11596
|
+
const call = (entrypoint) => provider.callContract({ contractAddress: coinAddress, entrypoint, calldata: [] });
|
|
11597
|
+
const [launchedRes, allocRes] = await Promise.all([
|
|
11598
|
+
call("is_launched").catch(() => null),
|
|
11599
|
+
call("get_team_allocation").catch(() => null)
|
|
11600
|
+
]);
|
|
11601
|
+
if (!launchedRes || !allocRes) return null;
|
|
11602
|
+
const [supplyRes, blockRes, liquidityRes] = await Promise.all([
|
|
11603
|
+
call("total_supply"),
|
|
11604
|
+
call("launched_at_block_number").catch(() => null),
|
|
11605
|
+
call("liquidity_type").catch(() => null)
|
|
11606
|
+
]);
|
|
11607
|
+
const isLaunched = BigInt(launchedRes[0] ?? "0x0") !== 0n;
|
|
11608
|
+
const totalSupply = u2563(supplyRes);
|
|
11609
|
+
const teamAllocation = u2563(allocRes);
|
|
11610
|
+
const teamAllocationPercent = totalSupply > 0n ? Number(teamAllocation * 10000n / totalSupply) / 100 : null;
|
|
11611
|
+
const launchedAtBlock = isLaunched && blockRes?.[0] != null ? Number(BigInt(blockRes[0])) : null;
|
|
11612
|
+
const liquidityPositionId = liquidityRes && BigInt(liquidityRes[0] ?? "0x1") === 0n && liquidityRes[2] != null ? BigInt(liquidityRes[2]).toString() : null;
|
|
12405
11613
|
return {
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
}
|
|
12413
|
-
const result = await executeSponsored(
|
|
12414
|
-
{ proxyUrl: deps.proxyUrl, fetchImpl: deps.fetchImpl },
|
|
12415
|
-
{
|
|
12416
|
-
address: userAddress,
|
|
12417
|
-
signTypedData: async (data) => signWithPrivateKey(privateKeyHex, typedData.getMessageHash(data, userAddress))
|
|
12418
|
-
},
|
|
12419
|
-
{ intentIds }
|
|
12420
|
-
);
|
|
12421
|
-
if (result.status === "sponsored") return { transactionHash: result.transactionHash };
|
|
12422
|
-
const consented = await deps.consent.request({ address: userAddress, calls });
|
|
12423
|
-
if (!consented) throw new SponsoredCallRejectedError(result.reason);
|
|
12424
|
-
return fallback.execute(input);
|
|
12425
|
-
}
|
|
11614
|
+
isLaunched,
|
|
11615
|
+
launchedAtBlock,
|
|
11616
|
+
totalSupplyRaw: totalSupply.toString(),
|
|
11617
|
+
teamAllocationRaw: teamAllocation.toString(),
|
|
11618
|
+
teamAllocationPercent,
|
|
11619
|
+
liquidityPositionId
|
|
12426
11620
|
};
|
|
12427
11621
|
}
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
body: JSON.stringify({
|
|
12439
|
-
ownerPubkey: input.ownerPubKey,
|
|
12440
|
-
ownerAddress: input.ownerAddress,
|
|
12441
|
-
salt: input.salt ?? "0x0"
|
|
12442
|
-
})
|
|
12443
|
-
});
|
|
12444
|
-
if (!buildRes.ok) {
|
|
12445
|
-
await describeFailure(buildRes, "We couldn't prepare your wallet deployment. Please try again.");
|
|
12446
|
-
}
|
|
12447
|
-
const { typedData, deployment, calls } = await buildRes.json();
|
|
12448
|
-
const account = new Account({
|
|
12449
|
-
provider: input.provider,
|
|
12450
|
-
address: input.ownerAddress,
|
|
12451
|
-
signer: input.privateKeyHex,
|
|
12452
|
-
cairoVersion: "1"
|
|
12453
|
-
});
|
|
12454
|
-
const signature = stark.signatureToHexArray(await account.signMessage(typedData));
|
|
12455
|
-
const executeRes = await doFetch(`${base}/execute`, {
|
|
12456
|
-
method: "POST",
|
|
12457
|
-
headers: { "Content-Type": "application/json" },
|
|
12458
|
-
body: JSON.stringify({ ownerAddress: input.ownerAddress, typedData, signature, deployment, calls })
|
|
12459
|
-
});
|
|
12460
|
-
if (!executeRes.ok) {
|
|
12461
|
-
await describeFailure(executeRes, "We couldn't complete your wallet deployment. Please try again.");
|
|
12462
|
-
}
|
|
12463
|
-
const { transactionHash } = await executeRes.json();
|
|
12464
|
-
return { transactionHash };
|
|
12465
|
-
}
|
|
12466
|
-
async function deploySelfFunded(input) {
|
|
12467
|
-
const classHash = getCoordinates("STARKNET").mediaWalletClassHash;
|
|
12468
|
-
if (!classHash) throw new Error("Media Wallet class hash is not configured");
|
|
12469
|
-
const account = new Account({
|
|
12470
|
-
provider: input.provider,
|
|
12471
|
-
address: input.ownerAddress,
|
|
12472
|
-
signer: input.privateKeyHex,
|
|
12473
|
-
cairoVersion: "1"
|
|
12474
|
-
});
|
|
12475
|
-
const { transaction_hash } = await account.deployAccount({
|
|
12476
|
-
classHash,
|
|
12477
|
-
constructorCalldata: ownerConstructorCalldata(input.ownerPubKey),
|
|
12478
|
-
addressSalt: 0,
|
|
12479
|
-
contractAddress: input.ownerAddress
|
|
12480
|
-
});
|
|
12481
|
-
return { transactionHash: transaction_hash };
|
|
11622
|
+
var factoryAddress = () => getStarknetCoordinates("STARKNET").creatorCoinFactory;
|
|
11623
|
+
function buildCreateCreatorCoinCall(params) {
|
|
11624
|
+
const salt = params.salt ?? BigInt("0x" + Date.now().toString(16));
|
|
11625
|
+
return populateCall(CreatorCoinFactoryABI, factoryAddress(), "create_creator_coin", [
|
|
11626
|
+
params.owner,
|
|
11627
|
+
params.name,
|
|
11628
|
+
params.symbol,
|
|
11629
|
+
BigInt(params.initialSupply),
|
|
11630
|
+
BigInt(salt)
|
|
11631
|
+
]);
|
|
12482
11632
|
}
|
|
12483
|
-
|
|
12484
|
-
const
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
12493
|
-
|
|
12494
|
-
|
|
11633
|
+
function buildLaunchOnEkuboCalls(params) {
|
|
11634
|
+
const ek = params.ekubo;
|
|
11635
|
+
const launchParameters = {
|
|
11636
|
+
creator_coin_address: params.creatorCoin,
|
|
11637
|
+
transfer_restriction_delay: params.transferRestrictionDelay ?? 0,
|
|
11638
|
+
max_percentage_buy_launch: params.maxPercentageBuyLaunch ?? 200,
|
|
11639
|
+
quote_address: params.quoteToken,
|
|
11640
|
+
initial_holders: params.initialHolders,
|
|
11641
|
+
initial_holders_amounts: params.initialHoldersAmounts.map((a) => BigInt(a))
|
|
11642
|
+
};
|
|
11643
|
+
const ekuboParameters = {
|
|
11644
|
+
fee: BigInt(ek.fee),
|
|
11645
|
+
tick_spacing: BigInt(ek.tickSpacing),
|
|
11646
|
+
starting_price: { mag: BigInt(ek.startingPrice.mag), sign: ek.startingPrice.sign },
|
|
11647
|
+
bound: BigInt(ek.bound)
|
|
11648
|
+
};
|
|
11649
|
+
const calls = [];
|
|
11650
|
+
if (params.quoteFundAmount !== void 0) {
|
|
11651
|
+
const amt = uint256.bnToUint256(BigInt(params.quoteFundAmount));
|
|
11652
|
+
calls.push({
|
|
11653
|
+
contractAddress: params.quoteToken,
|
|
11654
|
+
entrypoint: "transfer",
|
|
11655
|
+
calldata: [factoryAddress(), amt.low, amt.high]
|
|
11656
|
+
});
|
|
12495
11657
|
}
|
|
11658
|
+
calls.push(populateCall(CreatorCoinFactoryABI, factoryAddress(), "launch_on_ekubo", [launchParameters, ekuboParameters]));
|
|
11659
|
+
return calls;
|
|
12496
11660
|
}
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
const
|
|
12500
|
-
|
|
11661
|
+
var CREATOR_COIN_CREATED_SELECTOR = hash.getSelectorFromName("CreatorCoinCreated");
|
|
11662
|
+
function parseCreatorCoinCreated(receipt) {
|
|
11663
|
+
const factory = normalizeAddress("STARKNET", getStarknetCoordinates("STARKNET").creatorCoinFactory);
|
|
11664
|
+
for (const ev of receipt?.events ?? []) {
|
|
11665
|
+
let from;
|
|
12501
11666
|
try {
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
fetchImpl: deps.fetchImpl,
|
|
12506
|
-
...wallet
|
|
12507
|
-
});
|
|
12508
|
-
} catch (sponsoredErr) {
|
|
12509
|
-
try {
|
|
12510
|
-
await selfFunded({ provider: deps.provider(), ...wallet });
|
|
12511
|
-
} catch (selfFundedErr) {
|
|
12512
|
-
const sponsored2 = sponsoredErr instanceof Error ? sponsoredErr.message : String(sponsoredErr);
|
|
12513
|
-
const selfFunded2 = selfFundedErr instanceof Error ? selfFundedErr.message : String(selfFundedErr);
|
|
12514
|
-
throw new Error(`Sponsored deploy failed: ${sponsored2}. Self-funded fallback failed: ${selfFunded2}`);
|
|
12515
|
-
}
|
|
11667
|
+
from = normalizeAddress("STARKNET", ev.from_address ?? "");
|
|
11668
|
+
} catch {
|
|
11669
|
+
continue;
|
|
12516
11670
|
}
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
12520
|
-
|
|
12521
|
-
|
|
12522
|
-
|
|
12523
|
-
let sealed = options.forceNew ? null : deps.store.load();
|
|
12524
|
-
if (sealed && await (deps.isDeployedImpl ?? isDeployed)(deps.provider(), sealed.address).catch(() => false)) {
|
|
12525
|
-
sealed = null;
|
|
12526
|
-
}
|
|
12527
|
-
let privateKeyHex;
|
|
12528
|
-
if (!sealed) {
|
|
12529
|
-
onStep("creating-passkey");
|
|
12530
|
-
const created = await deps.passkey.createOwnerKey();
|
|
12531
|
-
sealed = created.sealed;
|
|
12532
|
-
privateKeyHex = created.privateKeyHex;
|
|
12533
|
-
deps.store.save(sealed);
|
|
12534
|
-
} else {
|
|
12535
|
-
privateKeyHex = await deps.passkey.unlockOwnerKey(sealed);
|
|
11671
|
+
if (from !== factory) continue;
|
|
11672
|
+
const k0 = ev.keys?.[0];
|
|
11673
|
+
if (!k0 || normalizeAddress("STARKNET", k0) !== normalizeAddress("STARKNET", CREATOR_COIN_CREATED_SELECTOR)) continue;
|
|
11674
|
+
const data = ev.data ?? [];
|
|
11675
|
+
if (data.length < 1) continue;
|
|
11676
|
+
return normalizeAddress("STARKNET", data[data.length - 1]);
|
|
12536
11677
|
}
|
|
12537
|
-
|
|
12538
|
-
await deployWallet(deps, { ownerAddress: sealed.address, ownerPubKey: sealed.ownerPubKey, privateKeyHex });
|
|
12539
|
-
deps.store.notifyChange();
|
|
12540
|
-
return { sealed };
|
|
12541
|
-
}
|
|
12542
|
-
function createDeploymentCoordinator(execute) {
|
|
12543
|
-
let inFlight = null;
|
|
12544
|
-
let currentStep = null;
|
|
12545
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
12546
|
-
return {
|
|
12547
|
-
run(onStep, options = {}) {
|
|
12548
|
-
if (inFlight) {
|
|
12549
|
-
if (options.forceNew) {
|
|
12550
|
-
return Promise.reject(new Error("A wallet setup is already in progress."));
|
|
12551
|
-
}
|
|
12552
|
-
if (currentStep) onStep(currentStep);
|
|
12553
|
-
listeners.add(onStep);
|
|
12554
|
-
return inFlight.finally(() => listeners.delete(onStep));
|
|
12555
|
-
}
|
|
12556
|
-
listeners.add(onStep);
|
|
12557
|
-
let started;
|
|
12558
|
-
try {
|
|
12559
|
-
started = execute((step) => {
|
|
12560
|
-
currentStep = step;
|
|
12561
|
-
for (const listener of listeners) listener(step);
|
|
12562
|
-
}, options);
|
|
12563
|
-
} catch (err) {
|
|
12564
|
-
listeners.clear();
|
|
12565
|
-
return Promise.reject(err);
|
|
12566
|
-
}
|
|
12567
|
-
const run = started.finally(() => {
|
|
12568
|
-
inFlight = null;
|
|
12569
|
-
currentStep = null;
|
|
12570
|
-
listeners.clear();
|
|
12571
|
-
});
|
|
12572
|
-
inFlight = run;
|
|
12573
|
-
return run;
|
|
12574
|
-
},
|
|
12575
|
-
isDeploying: () => inFlight !== null
|
|
12576
|
-
};
|
|
12577
|
-
}
|
|
12578
|
-
|
|
12579
|
-
// src/wallet/client.ts
|
|
12580
|
-
function describeDevices(owners, thisDevicePubkey) {
|
|
12581
|
-
const mine = computeOwnerGuid(thisDevicePubkey);
|
|
12582
|
-
return owners.map((owner) => ({
|
|
12583
|
-
guid: owner.guid,
|
|
12584
|
-
type: owner.type,
|
|
12585
|
-
isThisDevice: BigInt(owner.guid) === BigInt(mine)
|
|
12586
|
-
}));
|
|
12587
|
-
}
|
|
12588
|
-
function canRemoveDevice(devices, guid) {
|
|
12589
|
-
if (devices.length <= 1) return false;
|
|
12590
|
-
return devices.some((device) => BigInt(device.guid) === BigInt(guid));
|
|
11678
|
+
throw new Error("Coin deployed but the coin address could not be read from the receipt");
|
|
12591
11679
|
}
|
|
12592
|
-
function
|
|
12593
|
-
const
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
|
|
12597
|
-
passkey: config.passkey,
|
|
12598
|
-
provider: config.provider,
|
|
12599
|
-
deployProxyUrl: config.deployProxyUrl,
|
|
12600
|
-
fetchImpl: config.fetchImpl
|
|
12601
|
-
};
|
|
12602
|
-
return completeDeployment(deps, onStep, options);
|
|
12603
|
-
});
|
|
12604
|
-
const unlockCache = /* @__PURE__ */ new Map();
|
|
12605
|
-
const lock = (address) => {
|
|
12606
|
-
const entry = unlockCache.get(address);
|
|
12607
|
-
if (!entry) return;
|
|
12608
|
-
clearTimeout(entry.timer);
|
|
12609
|
-
unlockCache.delete(address);
|
|
12610
|
-
};
|
|
12611
|
-
const unlockOnce = (sealed) => {
|
|
12612
|
-
const existing = unlockCache.get(sealed.address);
|
|
12613
|
-
if (existing) return existing.promise;
|
|
12614
|
-
const promise = config.passkey.unlockOwnerKey(sealed).catch((err) => {
|
|
12615
|
-
lock(sealed.address);
|
|
12616
|
-
throw err;
|
|
12617
|
-
});
|
|
12618
|
-
const timer = setTimeout(() => lock(sealed.address), ttl);
|
|
12619
|
-
unlockCache.set(sealed.address, { promise, timer });
|
|
12620
|
-
return promise;
|
|
12621
|
-
};
|
|
12622
|
-
const run = async (sealed, calls, userAddress, intentIds) => {
|
|
12623
|
-
const privateKeyHex = await unlockOnce(sealed);
|
|
12624
|
-
return config.executor.execute({
|
|
12625
|
-
userAddress: userAddress ?? sealed.address,
|
|
12626
|
-
privateKeyHex,
|
|
12627
|
-
calls,
|
|
12628
|
-
intentIds
|
|
12629
|
-
});
|
|
12630
|
-
};
|
|
12631
|
-
const walletIntents = config.walletIntents ?? (async (params) => {
|
|
12632
|
-
if (!config.backendUrl) throw new Error("This wallet has no backend url configured");
|
|
12633
|
-
const created = await new ApiClient(config.backendUrl).createWalletManageIntent(params);
|
|
12634
|
-
return created.data;
|
|
11680
|
+
async function isCreatorCoin(provider, address) {
|
|
11681
|
+
const res = await provider.callContract({
|
|
11682
|
+
contractAddress: factoryAddress(),
|
|
11683
|
+
entrypoint: "is_creator_coin",
|
|
11684
|
+
calldata: [address]
|
|
12635
11685
|
});
|
|
12636
|
-
|
|
12637
|
-
const intent = await walletIntents(params);
|
|
12638
|
-
const { transactionHash } = await run(sealed, intent.calls, params.owner, [intent.id]);
|
|
12639
|
-
return transactionHash;
|
|
12640
|
-
};
|
|
12641
|
-
return {
|
|
12642
|
-
store: config.store,
|
|
12643
|
-
passkey: config.passkey,
|
|
12644
|
-
lock,
|
|
12645
|
-
signerFor(sealed) {
|
|
12646
|
-
return {
|
|
12647
|
-
address: sealed.address,
|
|
12648
|
-
signTypedData: async (data) => {
|
|
12649
|
-
const privateKeyHex = await unlockOnce(sealed);
|
|
12650
|
-
return signWithPrivateKey(privateKeyHex, typedData.getMessageHash(data, sealed.address));
|
|
12651
|
-
},
|
|
12652
|
-
execute: async (calls, opts) => {
|
|
12653
|
-
const { transactionHash } = await run(sealed, calls, void 0, opts?.intentIds);
|
|
12654
|
-
return { txHash: transactionHash };
|
|
12655
|
-
}
|
|
12656
|
-
};
|
|
12657
|
-
},
|
|
12658
|
-
run,
|
|
12659
|
-
getGuardians: (address) => getGuardians(config.provider(), address),
|
|
12660
|
-
getEscape: (address) => getEscape(config.provider(), address),
|
|
12661
|
-
getEscapeSecurityPeriod: (address) => getEscapeSecurityPeriod(config.provider(), address),
|
|
12662
|
-
getOwners: (address) => getOwners(config.provider(), address),
|
|
12663
|
-
async isOwnerOf(accountAddress, devicePubkey) {
|
|
12664
|
-
const owners = await getOwners(config.provider(), accountAddress);
|
|
12665
|
-
const guid = BigInt(computeOwnerGuid(devicePubkey));
|
|
12666
|
-
return owners.some((owner) => BigInt(owner.guid) === guid);
|
|
12667
|
-
},
|
|
12668
|
-
setFirstGuardian: (sealed, guardianPubkey) => manage(sealed, { owner: sealed.address, action: "set_first_guardian", pubkey: guardianPubkey }),
|
|
12669
|
-
triggerEscapeOwner: (guardianSealed, targetAddress, newOwnerPubkey) => manage(guardianSealed, { owner: normalizeWalletAddress(targetAddress), action: "trigger_escape", newOwnerPubkey }),
|
|
12670
|
-
completeEscapeOwner: (guardianSealed, targetAddress) => manage(guardianSealed, { owner: normalizeWalletAddress(targetAddress), action: "complete_escape" }),
|
|
12671
|
-
cancelEscape: (sealed) => manage(sealed, { owner: sealed.address, action: "cancel_escape" }),
|
|
12672
|
-
addDevice: (sealed, devicePubkey) => manage(sealed, { owner: sealed.address, action: "add_owner", pubkey: devicePubkey }),
|
|
12673
|
-
removeDevice: (sealed, ownerGuid) => manage(sealed, { owner: sealed.address, action: "remove_owner", ownerGuid }),
|
|
12674
|
-
completeDeployment: (onStep, options) => deployments.run(onStep, options),
|
|
12675
|
-
isDeploying: () => deployments.isDeploying()
|
|
12676
|
-
};
|
|
11686
|
+
return BigInt(res[0] ?? "0x0") === 1n;
|
|
12677
11687
|
}
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
11688
|
+
function encodeByteArray(str) {
|
|
11689
|
+
const bytes = new TextEncoder().encode(str);
|
|
11690
|
+
const fullChunks = [];
|
|
11691
|
+
let i = 0;
|
|
11692
|
+
while (i + 31 <= bytes.length) {
|
|
11693
|
+
let val = 0n;
|
|
11694
|
+
for (const b of bytes.slice(i, i + 31)) {
|
|
11695
|
+
val = val << 8n | BigInt(b);
|
|
11696
|
+
}
|
|
11697
|
+
fullChunks.push(num.toHex(val));
|
|
11698
|
+
i += 31;
|
|
11699
|
+
}
|
|
11700
|
+
const remaining = bytes.slice(i);
|
|
11701
|
+
let pendingVal = 0n;
|
|
11702
|
+
for (const b of remaining) {
|
|
11703
|
+
pendingVal = pendingVal << 8n | BigInt(b);
|
|
11704
|
+
}
|
|
11705
|
+
return [
|
|
11706
|
+
fullChunks.length.toString(),
|
|
11707
|
+
...fullChunks,
|
|
11708
|
+
num.toHex(pendingVal),
|
|
11709
|
+
remaining.length.toString()
|
|
11710
|
+
];
|
|
12687
11711
|
}
|
|
12688
11712
|
|
|
12689
|
-
export { MAX_SUPPLY as COIN_MAX_SUPPLY, MIN_SUPPLY as COIN_MIN_SUPPLY,
|
|
11713
|
+
export { MAX_SUPPLY as COIN_MAX_SUPPLY, MIN_SUPPLY as COIN_MIN_SUPPLY, CreatorCoinFactoryABI, DROP_MAX_CLAIM_QUANTITY, DropCollectionABI, DropFactoryABI, FundingTransferNotSentError, IPClubCollectionABI, IPClubFactoryABI, IPCollection1155ABI, IPCollection1155FactoryABI, IPCollectionABI, IPGenesisABI, IPMarketplaceABI, IPNftABI, IPSponsorshipABI, IPTicketCollectionABI, IPTicketCollectionFactoryABI, MAX_HOLDERS_AT_LAUNCH, MAX_TEAM_ALLOCATION_PERCENT, Medialane1155ABI, MedialaneClient, POPCollectionABI, POPFactoryABI, SUGGESTED_DEFAULT_PRICE, StarknetVenue, VALIDATED_EKUBO_PARAMS, apiKeyConfirmationTypedData, assertTransactionSucceeded, build1155CancellationTypedData, build1155OrderTypedData, buildCancellationTypedData, buildCreateCreatorCoinCall, buildDropClaimCalls, buildFeeCall, buildFundingTransferCall, buildLaunchOnEkuboCalls, buildOrderTypedData, buildPopAllowlist, buybackQuoteRaw, clubCalls, toRaw as coinToRaw, confirmIntentBestEffort, createChainProvider, decodePopClaimFragment, deployedCollectionFromReceipt, dropCalls, dropClaimLinks, dropClaimedBy, dropMintCost, dropMintState, editionCalls, encodeByteArray, encodePopClaimFragment, executeIntent, executeIntents, fdvHuman, feeAmount, feeBps, fundWithChainTransfer, fundingApiFor, getCreatorCoinGuarantees, getSiwsStorageKey, getStoredSiwsToken, isCreatorCoin, isSiwsTokenValid, mintedTokenIdFromReceipt, normalizeSiwsSignature, parseCreatorCoinCreated, popCalls, popClaimInfo, popClaimLinks, popClaimLinksCsv, popClaimState, popFactoryCalls, popHasClaimed, populateCall, priceToEkuboParams, readDrop, requestSiwsToken, signInWithWallet, sponsorshipCalls, storeSiwsToken, syncTransactionBestEffort, teamCoinsRaw, ticketCalls, toContractTerms as toDropContractTerms, validateName as validateCoinName, validateSupply as validateCoinSupply, validateSymbol as validateCoinSymbol, validatePrice, verifyPopProof };
|
|
12690
11714
|
//# sourceMappingURL=index.js.map
|
|
12691
11715
|
//# sourceMappingURL=index.js.map
|