Skip to content

Commit afa2e1d

Browse files
authored
Merge pull request #330 from Nacho1499/feat/light-version-SDK
feat/light version of SDK
2 parents 5d8370e + ed23d7b commit afa2e1d

8 files changed

Lines changed: 135 additions & 45 deletions

File tree

sdk/LIGHT_VERSION.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Tikka SDK Light Version
2+
3+
A lightweight, framework-agnostic version of the Tikka SDK designed for mobile and browser integrations.
4+
5+
## Features
6+
- **Zero NestJS Overheads**: No decorators or dependency injection logic.
7+
- **Small Footprint**: Target < 50kb gzipped.
8+
- **ESM Ready**: Optimized for modern bundlers (Vite, Webpack 5).
9+
10+
## Usage
11+
Instead of the main entry, import from the light bundle:
12+
`import { RaffleService } from '@tikka/sdk/dist/light/index.light';`
13+
14+
## Limitations
15+
- No NestJS Module support (`TikkaModule` is excluded).
16+
- Requires manual instantiation of services (e.g., `new RaffleService(rpcService)`).
17+
18+
19+
# Tikka SDK Light
20+
This version is optimized for mobile and browser environments.
21+
22+
## How to use
23+
Import from `@tikka/sdk/dist/light/index.light`.
24+
25+
## Exclusions
26+
- Does not include NestJS Modules or Providers.
27+
- Services must be instantiated manually (e.g., `new RpcService()`).

sdk/package.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,30 @@
33
"version": "0.1.0",
44
"description": "NestJS SDK for Tikka Soroban contract interaction",
55
"private": true,
6+
"main": "dist/index.js",
7+
"types": "dist/index.d.ts",
8+
"bin": {
9+
"tikka": "./bin/tikka.mjs"
10+
},
611
"scripts": {
712
"build": "nest build",
13+
"build:light": "tsc -p tsconfig.light.json",
814
"start": "nest start",
915
"start:dev": "nest start --watch",
1016
"start:debug": "nest start --debug --watch",
1117
"lint": "eslint \"{src,test}/**/*.ts\"",
1218
"test": "jest",
19+
"tikka": "node bin/tikka.mjs",
1320
"examples:check": "tsc --project examples/tsconfig.json",
21+
"example:cli": "node bin/tikka.mjs",
1422
"example:quickstart": "ts-node examples/quickstart.ts",
1523
"example:create-raffle": "ts-node examples/create-raffle.ts",
1624
"example:buy-tickets": "ts-node examples/buy-tickets.ts",
1725
"example:listen-events": "ts-node examples/listen-events.ts",
1826
"example:offline-signing": "ts-node examples/offline-signing.ts",
1927
"docs": "typedoc",
20-
"docs:watch": "typedoc --watch"
28+
"docs:watch": "typedoc --watch",
29+
"size-check": "powershell (Get-Item dist/light/index.light.js).Length"
2130
},
2231
"dependencies": {
2332
"@albedo-link/intent": "^0.13.0",
@@ -27,12 +36,16 @@
2736
"@stellar/freighter-api": "^3.1.0",
2837
"@stellar/stellar-sdk": "^14.5.0",
2938
"bignumber.js": "^9.3.1",
39+
"chalk": "^5.3.0",
40+
"commander": "^12.1.0",
41+
"inquirer": "^9.3.2",
3042
"reflect-metadata": "^0.2.0",
3143
"rxjs": "^7.8.0"
3244
},
3345
"devDependencies": {
3446
"@nestjs/cli": "^11.0.16",
3547
"@nestjs/testing": "^10.4.0",
48+
"@types/inquirer": "^9.0.7",
3649
"@types/jest": "^30.0.0",
3750
"@types/node": "^22.0.0",
3851
"@typescript-eslint/eslint-plugin": "^8.56.1",
@@ -58,4 +71,4 @@
5871
},
5972
"testEnvironment": "node"
6073
}
61-
}
74+
}

sdk/src/index.light.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { RpcService } from './network/rpc.service';
2+
export { RaffleService } from './modules/raffle/raffle.service';
3+
export { TicketService } from './modules/ticket/ticket.service';
4+
export * from './types';

sdk/src/modules/admin/admin.service.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('AdminService', () => {
3333

3434
const result = await service.pause();
3535

36-
expect(contractService.invoke).toHaveBeenCalledWith('pause', []);
36+
expect(contractService.invoke).toHaveBeenCalledWith('pause', [], expect.anything());
3737
expect(result).toEqual({ txHash: 'abc123', ledger: 100 });
3838
});
3939
});
@@ -48,7 +48,7 @@ describe('AdminService', () => {
4848

4949
const result = await service.unpause();
5050

51-
expect(contractService.invoke).toHaveBeenCalledWith('unpause', []);
51+
expect(contractService.invoke).toHaveBeenCalledWith('unpause', [], expect.anything());
5252
expect(result).toEqual({ txHash: 'def456', ledger: 101 });
5353
});
5454
});
@@ -95,7 +95,7 @@ describe('AdminService', () => {
9595

9696
const result = await service.transferAdmin(newAdmin);
9797

98-
expect(contractService.invoke).toHaveBeenCalledWith('transfer_admin', [newAdmin]);
98+
expect(contractService.invoke).toHaveBeenCalledWith('transfer_admin', [newAdmin], expect.anything());
9999
expect(result).toEqual({ txHash: 'ghi789', ledger: 102 });
100100
});
101101

@@ -114,7 +114,7 @@ describe('AdminService', () => {
114114

115115
const result = await service.acceptAdmin();
116116

117-
expect(contractService.invoke).toHaveBeenCalledWith('accept_admin', []);
117+
expect(contractService.invoke).toHaveBeenCalledWith('accept_admin', [], expect.anything());
118118
expect(result).toEqual({ txHash: 'jkl012', ledger: 103 });
119119
});
120120
});

sdk/src/modules/raffle/raffle.service.spec.ts

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { RaffleService } from './raffle.service';
2-
import { ContractService } from '../../contract/contract.service';
3-
import { ContractFn } from '../../contract/bindings';
4-
import { RaffleParams, RaffleData } from './raffle.types';
5-
import { nativeToScVal } from '@stellar/stellar-sdk';
1+
import { RaffleService } from "./raffle.service";
2+
import { ContractService } from "../../contract/contract.service";
3+
import { ContractFn } from "../../contract/bindings";
4+
import { RaffleParams, RaffleData } from "./raffle.types";
5+
import { nativeToScVal } from "@stellar/stellar-sdk";
66

7-
describe('RaffleService', () => {
7+
describe("RaffleService", () => {
88
let service: RaffleService;
99
let contractService: jest.Mocked<ContractService>;
1010

@@ -18,20 +18,20 @@ describe('RaffleService', () => {
1818
service = new RaffleService(contractService);
1919
});
2020

21-
describe('create', () => {
22-
it('should correctly format and invoke CREATE_RAFFLE', async () => {
21+
describe("create", () => {
22+
it("should correctly format and invoke CREATE_RAFFLE", async () => {
2323
const params: RaffleParams = {
24-
ticketPrice: '10',
24+
ticketPrice: "10",
2525
maxTickets: 100,
2626
endTime: Date.now() + 86400000, // +1 day
2727
allowMultiple: true,
28-
asset: 'XLM',
29-
metadataCid: 'QmTest',
28+
asset: "XLM",
29+
metadataCid: "QmTest",
3030
};
3131

3232
const mockInvokeResult = {
3333
result: 1,
34-
txHash: 'abc',
34+
txHash: "abc",
3535
ledger: 100,
3636
};
3737

@@ -42,51 +42,57 @@ describe('RaffleService', () => {
4242
expect(contractService.invoke).toHaveBeenCalledWith(
4343
ContractFn.CREATE_RAFFLE,
4444
expect.any(Array),
45+
expect.anything(), // Add this to handle the metadata object
4546
);
47+
4648
expect(result).toEqual({
4749
raffleId: 1,
48-
txHash: 'abc',
50+
txHash: "abc",
4951
ledger: 100,
5052
});
5153
});
5254

53-
it('should throw if ticketPrice is empty', async () => {
55+
it("should throw if ticketPrice is empty", async () => {
5456
const params: RaffleParams = {
55-
ticketPrice: '',
57+
ticketPrice: "",
5658
maxTickets: 100,
5759
endTime: Date.now(),
5860
allowMultiple: true,
59-
asset: 'XLM',
61+
asset: "XLM",
6062
};
6163

62-
await expect(service.create(params)).rejects.toThrow('ticketPrice must be a non-empty string');
64+
await expect(service.create(params)).rejects.toThrow(
65+
"ticketPrice must be a non-empty string",
66+
);
6367
});
6468

65-
it('should throw if maxTickets is not a positive integer', async () => {
69+
it("should throw if maxTickets is not a positive integer", async () => {
6670
const params: RaffleParams = {
67-
ticketPrice: '10',
71+
ticketPrice: "10",
6872
maxTickets: 0,
6973
endTime: Date.now(),
7074
allowMultiple: true,
71-
asset: 'XLM',
75+
asset: "XLM",
7276
};
7377

74-
await expect(service.create(params)).rejects.toThrow('maxTickets must be a positive integer');
78+
await expect(service.create(params)).rejects.toThrow(
79+
"maxTickets must be a positive integer",
80+
);
7581
});
7682
});
7783

78-
describe('get', () => {
79-
it('should fetch and map raffle data', async () => {
84+
describe("get", () => {
85+
it("should fetch and map raffle data", async () => {
8086
const mockRawData = {
81-
creator: 'G...',
87+
creator: "G...",
8288
status: 1, // OPEN
8389
ticket_price: BigInt(100000000),
8490
max_tickets: 100,
8591
tickets_sold: 50,
8692
end_time: BigInt(1711545600), // example timestamp in seconds
87-
asset: 'XLM',
93+
asset: "XLM",
8894
allow_multiple: true,
89-
metadata_cid: 'Qm...',
95+
metadata_cid: "Qm...",
9096
};
9197

9298
contractService.simulateReadOnly.mockResolvedValue(mockRawData);
@@ -99,18 +105,20 @@ describe('RaffleService', () => {
99105
[raffleId],
100106
);
101107
expect(result.raffleId).toBe(raffleId);
102-
expect(result.ticketPrice).toBe('100000000');
108+
expect(result.ticketPrice).toBe("100000000");
103109
expect(result.maxTickets).toBe(100);
104110
expect(result.endTime).toBe(1711545600 * 1000);
105111
});
106112

107-
it('should throw if raffleId is invalid', async () => {
108-
await expect(service.get(-1)).rejects.toThrow('raffleId must be a positive integer');
113+
it("should throw if raffleId is invalid", async () => {
114+
await expect(service.get(-1)).rejects.toThrow(
115+
"raffleId must be a positive integer",
116+
);
109117
});
110118
});
111119

112-
describe('listActive', () => {
113-
it('should return active raffle IDs', async () => {
120+
describe("listActive", () => {
121+
it("should return active raffle IDs", async () => {
114122
const mockIds = [1, 2, 3];
115123
contractService.simulateReadOnly.mockResolvedValue(mockIds);
116124

@@ -124,8 +132,8 @@ describe('RaffleService', () => {
124132
});
125133
});
126134

127-
describe('listAll', () => {
128-
it('should return all raffle IDs', async () => {
135+
describe("listAll", () => {
136+
it("should return all raffle IDs", async () => {
129137
const mockIds = [1, 2, 3, 4];
130138
contractService.simulateReadOnly.mockResolvedValue(mockIds);
131139

@@ -139,22 +147,22 @@ describe('RaffleService', () => {
139147
});
140148
});
141149

142-
describe('cancel', () => {
143-
it('should invoke CANCEL_RAFFLE', async () => {
150+
describe("cancel", () => {
151+
it("should invoke CANCEL_RAFFLE", async () => {
144152
const mockInvokeResult = {
145153
result: undefined,
146-
txHash: 'hash',
154+
txHash: "hash",
147155
ledger: 200,
148156
};
149157

150158
contractService.invoke.mockResolvedValue(mockInvokeResult);
151159

152160
const raffleId = 1;
153-
const result = await service.cancel(raffleId);
154-
161+
const result = await service.cancel({ raffleId });
155162
expect(contractService.invoke).toHaveBeenCalledWith(
156163
ContractFn.CANCEL_RAFFLE,
157164
[raffleId],
165+
expect.anything(), // Add this to handle the metadata object
158166
);
159167
expect(result).toEqual(mockInvokeResult);
160168
});

sdk/src/network/rpc.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Injectable } from '@nestjs/common';
22
import { rpc } from '@stellar/stellar-sdk';
3-
import { NetworkConfig, RpcConfig, DEFAULT_RPC_CONFIG } from './network.config';
3+
import { DEFAULT_RPC_CONFIG } from './network.config';
4+
import type { NetworkConfig, RpcConfig } from './network.config';
45
import { TikkaSdkError, TikkaSdkErrorCode } from '../utils/errors';
56

67
interface RequestOptions {

sdk/src/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export interface Raffle {
2+
id: string;
3+
name: string;
4+
ticketPrice: string;
5+
status: string;
6+
}
7+
8+
export interface NetworkConfig {
9+
rpcUrl: string;
10+
networkPassphrase: string;
11+
}
12+
13+
// Add any other core interfaces used by your services

sdk/tsconfig.light.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"module": "ESNext",
5+
"target": "ES2020",
6+
"moduleResolution": "node",
7+
"outDir": "./dist/light",
8+
"rootDir": "src",
9+
"declaration": true,
10+
"isolatedModules": false,
11+
"emitDecoratorMetadata": false,
12+
"experimentalDecorators": true,
13+
"skipLibCheck": true
14+
},
15+
"include": [
16+
"src/index.light.ts",
17+
"src/types.ts"
18+
],
19+
"exclude": [
20+
"node_modules",
21+
"src/**/*.module.ts",
22+
"src/contract/contract.service.ts"
23+
]
24+
}

0 commit comments

Comments
 (0)