Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 91 additions & 55 deletions tutorials/car-sales.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
/**
* Tutorial: Car Sales Management
*
* Original code from: https://dashpay.github.io/platform/evo-sdk/tutorials/car-sales.html
* NOTE: This code does NOT compile against @dashevo/evo-sdk@3.1.0-dev.1
* Corrected to match the actual @dashevo/evo-sdk@3.1.0-dev.1 API.
* Original: https://dashpay.github.io/platform/evo-sdk/tutorials/car-sales.html
*/

// @ts-nocheck — original tutorial code, kept verbatim for diffing

import { EvoSDK, wallet } from '@dashevo/evo-sdk';
import {
EvoSDK,
DataContract,
Document,
Identifier,
IdentitySigner,
} from '@dashevo/evo-sdk';

// ──────────────────────────────────────────────
// Step 1: Design the data contract
// Step 1: Design the data contract (unchanged)
// ──────────────────────────────────────────────

const carSalesSchema = {
Expand Down Expand Up @@ -54,28 +58,46 @@ const identityId = 'YOUR_IDENTITY_ID';
const privateKeyWif = 'YOUR_PRIVATE_KEY_WIF';
const signingKeyIndex = 0;

// Fetch identity to get the signing key
const identity = await sdk.identities.fetch(identityId);
if (!identity) throw new Error('Identity not found');

const identityKey = identity.publicKeys[signingKeyIndex];

// Create a signer with your private key
const signer = new IdentitySigner();
signer.addKeyFromWif(privateKeyWif);

// Get the identity nonce for contract ID generation
const identityNonce = await sdk.identities.nonce(identityId);
if (identityNonce === undefined) throw new Error('Could not fetch nonce');

// Construct the DataContract object
const dataContract = new DataContract({
ownerId: identityId,
identityNonce,
schemas: carSalesSchema,
});

// Publish the data contract
const contract = await sdk.contracts.publish({
identityId,
documentSchemas: carSalesSchema,
privateKeyWif,
signingKeyIndex,
nonce: await sdk.identities.nonce(identityId),
dataContract,
identityKey,
signer,
});

const contractId = contract.getId().toString();
const contractId = contract.id.toString();
console.log('Contract published:', contractId);

// ──────────────────────────────────────────────
// Step 3: Create a listing
// ──────────────────────────────────────────────

const nonce = await sdk.identities.contractNonce(identityId, contractId);

await sdk.documents.create({
contractId,
documentType: 'listing',
document: {
const listingDoc = new Document({
documentTypeName: 'listing',
dataContractId: contractId,
ownerId: identityId,
properties: {
make: 'Toyota',
model: 'Camry',
year: 2021,
Expand All @@ -84,10 +106,12 @@ await sdk.documents.create({
description: 'Well-maintained, single owner, full service history.',
status: 'available',
},
identityId,
privateKeyWif,
signingKeyIndex,
nonce,
});

await sdk.documents.create({
document: listingDoc,
identityKey,
signer,
});

console.log('Listing created!');
Expand All @@ -98,24 +122,24 @@ console.log('Listing created!');

// Fetch all available listings
const results = await sdk.documents.query({
contractId,
documentType: 'listing',
dataContractId: contractId,
documentTypeName: 'listing',
where: [['status', '==', 'available']],
orderBy: [['priceUsd', 'asc']],
limit: 20,
});

for (const [id, doc] of results) {
if (!doc) continue;
const data = doc.getData();
const data = doc.properties as Record<string, unknown>;
console.log(`${data.year} ${data.make} ${data.model} — $${data.priceUsd}`);
console.log(` ID: ${id}`);
}

// Search by make
const toyotas = await sdk.documents.query({
contractId,
documentType: 'listing',
dataContractId: contractId,
documentTypeName: 'listing',
where: [
['make', '==', 'Toyota'],
['status', '==', 'available'],
Expand All @@ -124,28 +148,28 @@ const toyotas = await sdk.documents.query({
});

// ──────────────────────────────────────────────
// Step 5: Update a listing
// Step 5: Update a listing (mark as sold)
// ──────────────────────────────────────────────

const listingId = 'THE_LISTING_DOCUMENT_ID';

// Fetch the existing document first
const existingDoc = await sdk.documents.get(contractId, 'listing', listingId);
if (!existingDoc) throw new Error('Listing not found');

// Update the properties
existingDoc.properties = {
...existingDoc.properties,
status: 'sold',
};

// Increment the revision
existingDoc.revision = (existingDoc.revision ?? 0n) + 1n;

await sdk.documents.replace({
contractId,
documentType: 'listing',
documentId: listingId,
document: {
make: 'Toyota',
model: 'Camry',
year: 2021,
mileageKm: 45000,
priceUsd: 22500,
description: 'Well-maintained, single owner, full service history.',
status: 'sold',
},
identityId,
privateKeyWif,
signingKeyIndex,
nonce: await sdk.identities.contractNonce(identityId, contractId),
document: existingDoc,
identityKey,
signer,
});

console.log('Listing marked as sold');
Expand All @@ -154,28 +178,39 @@ console.log('Listing marked as sold');
// Step 6: Leave a review
// ──────────────────────────────────────────────

// Buyer's credentials
const buyerIdentityId = 'BUYER_IDENTITY_ID';
const buyerKeyWif = 'BUYER_PRIVATE_KEY_WIF';

await sdk.documents.create({
contractId,
documentType: 'review',
document: {
const buyerIdentity = await sdk.identities.fetch(buyerIdentityId);
if (!buyerIdentity) throw new Error('Buyer identity not found');

const buyerKey = buyerIdentity.publicKeys[0];
const buyerSigner = new IdentitySigner();
buyerSigner.addKeyFromWif(buyerKeyWif);

const reviewDoc = new Document({
documentTypeName: 'review',
dataContractId: contractId,
ownerId: buyerIdentityId,
properties: {
sellerId: 'SELLER_IDENTITY_ID',
listingId: 'THE_LISTING_DOCUMENT_ID',
rating: 5,
comment: 'Great seller, car was exactly as described!',
},
identityId: buyerIdentityId,
privateKeyWif: buyerKeyWif,
signingKeyIndex: 0,
nonce: await sdk.identities.contractNonce(buyerIdentityId, contractId),
});

await sdk.documents.create({
document: reviewDoc,
identityKey: buyerKey,
signer: buyerSigner,
});

// Query reviews for a seller
const reviews = await sdk.documents.query({
contractId,
documentType: 'review',
dataContractId: contractId,
documentTypeName: 'review',
where: [['sellerId', '==', 'SELLER_IDENTITY_ID']],
orderBy: [['rating', 'desc']],
limit: 50,
Expand All @@ -185,7 +220,8 @@ let totalRating = 0;
let count = 0;
for (const [, doc] of reviews) {
if (!doc) continue;
totalRating += doc.getData().rating;
const data = doc.properties as Record<string, unknown>;
totalRating += data.rating as number;
count++;
}
console.log(`Average rating: ${(totalRating / count).toFixed(1)} (${count} reviews)`);