Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade version to 1.1.0 #97

Merged
merged 25 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
def679c
Merge pull request #92 from ainize-team/release/1.0.6
yoojinko Jan 3, 2024
a9fb37b
blockchainFilter
akastercomcom Jan 4, 2024
1383ce3
fix: add await
akastercomcom Jan 4, 2024
eef0e3d
feat: add signer functions
yoojinko Jan 12, 2024
a23bea6
chore: update ain-js
yoojinko Jan 12, 2024
64576fa
feat: add signer login
yoojinko Jan 12, 2024
dc326dc
refactor: checkLoggedIn
yoojinko Jan 12, 2024
d1566ac
feat: add signer logout
yoojinko Jan 12, 2024
8506957
fix: if
akastercomcom Jan 22, 2024
d3b4f4b
merge develop'
akastercomcom Jan 22, 2024
cc26a96
Merge pull request #93 from ainize-team/feat/woojae/blockchainFilter
akastercomcom Jan 22, 2024
569d173
refactor: check logged in
yoojinko Jan 23, 2024
97a6f62
Merge pull request #94 from ainize-team/feature/yoojin/signer_login
yoojinko Jan 23, 2024
5696757
fix: await getAddress
yoojinko Jan 25, 2024
788d885
fix: add isAccountSetUp and check signer tx
yoojinko Jan 25, 2024
b99da6e
fix: subscribe data
yoojinko Jan 26, 2024
99abbf1
Merge pull request #95 from ainize-team/feature/yoojin/signer_login
yoojinko Jan 29, 2024
ba53f43
fix: path
akastercomcom Jan 30, 2024
2aaa4db
letterCase
akastercomcom Jan 30, 2024
dc4d34a
fix
akastercomcom Jan 30, 2024
34de664
Merge pull request #96 from ainize-team/fix/woojae/triggerFilter
akastercomcom Jan 30, 2024
9c69c12
Upgrade version to 1.1.0
yoojinko Jan 30, 2024
ad595e8
fix: remove log
yoojinko Jan 30, 2024
5ba3fdc
docs: readme
yoojinko Jan 30, 2024
786969e
docs: readme wallet ver
yoojinko Jan 31, 2024
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ You should login to ainize with AI Network account before deploy the container.
ainize.login(<YOUR_PRIVATE_KEY>);
```

You can also login using [AIN Wallet](https://chromewebstore.google.com/detail/ain-wallet/hbdheoebpgogdkagfojahleegjfkhkpl) on the web.
```typescript
ainize.loginWithSigner();
```
This feature is supported from AIN Wallet version 2.0.5 or later.

### Deploy
You can deploy your AI service to ainize.
```typescript
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ainize-team/ainize-js",
"version": "1.0.6",
"version": "1.1.0",
"main": "dist/ainize.js",
"types": "dist/ainize.d.ts",
"scripts": {
Expand Down Expand Up @@ -42,7 +42,7 @@
"typescript": "^4.6.3"
},
"dependencies": {
"@ainblockchain/ain-js": "^1.3.5",
"@ainblockchain/ain-js": "^1.6.3",
"axios": "^0.26.1",
"express": "^4.18.2",
"fast-json-stable-stringify": "^2.1.0",
Expand Down
64 changes: 50 additions & 14 deletions src/ain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Ain from "@ainblockchain/ain-js";
import { getBlockChainEndpoint } from "./constants";
import { TransactionBody } from "@ainblockchain/ain-util";
import { txResult } from "./types/type";
import { Signer } from "@ainblockchain/ain-js/lib/signer/signer";
import { DefaultSigner } from "@ainblockchain/ain-js/lib/signer/default-signer"

// NOTE(yoojin): Plz suggest a good name.
export default class AinModule {
Expand All @@ -20,12 +22,6 @@ export default class AinModule {
this.ain = new Ain(blockchainEndpoint, chainId);
}

isDefaultAccountExist(): boolean {
if (this.getDefaultAccount())
return true;
return false;
}

createAccount() {
this.checkAinInitiated();
const newAccount = this.ain!.wallet.create(1)[0];
Expand All @@ -39,39 +35,72 @@ export default class AinModule {
this.ain!.wallet.addAndSetDefaultAccount(privateKey);
}

setSigner(signer: Signer) {
this.checkAinInitiated();
this.ain!.setSigner(signer);
}

getDefaultAccount() {
this.checkAinInitiated();
return this.ain!.wallet.defaultAccount;
}

getSigner() {
this.checkAinInitiated();
return this.ain!.signer
}

async getAddress() {
this.checkAinInitiated();
try {
return this.getSigner().getAddress();
} catch (e) {
throw new Error("Need to set up an account or signer first.");
}
}

isAccountSetUp() {
try {
this.checkAinInitiated();
this.getSigner().getAddress();
return true;
} catch (e) {
return false;
}
}

removeDefaultAccount() {
this.checkAinInitiated();
this.ain!.wallet.removeDefaultAccount();
}

getAddress() {
this.isDefaultAccountExist();
return this.ain!.wallet.defaultAccount!.address;
removeSigner() {
this.checkAinInitiated();
const wallet = this.ain!.wallet;
const provider = this.ain!.provider;
wallet.removeDefaultAccount();
this.ain!.setSigner(new DefaultSigner(wallet, provider))
}

async getBalance() {
this.isDefaultAccountExist();
return await this.ain!.wallet.getBalance();
const address = await this.getAddress();
const balancePath = `/accounts/${address}/balance`;
return await this.ain!.db.ref(balancePath).getValue();
}

async getValue(path: string) {
this.checkAinInitiated();
return await this.ain!.db.ref(path).getValue();
}

private async _sendTransaction(data: TransactionBody) {
private async _sendTransaction(txBody: TransactionBody) {
this.checkAinInitiated();
return await this.ain!.sendTransaction(data);
return await this.ain!.signer.sendTransaction(txBody);
}

private checkAinInitiated(): boolean {
if (!this.ain)
throw new Error('Set initAin(chainId) First.');
throw new Error('Set initAin(chainId) first.');
return true;
}

Expand All @@ -92,6 +121,13 @@ export default class AinModule {
private handleTxResultWrapper(operation: Function) {
return async (args: any) => {
const res = await operation(args);
// ainWalletSigner return txHash or undefined.
if (typeof res === 'string') {
return res;
} else if (res === undefined) {
throw new Error(`Failed to build transaction.`);
}
// defaultSigner return a result object of transactions.
const { tx_hash, result } = res;
if (this.hasFailedOpResultList(result)) {
throw new Error(
Expand Down
22 changes: 15 additions & 7 deletions src/ainize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { deployConfig } from "./types/type";
import AinModule from "./ain";
import Internal from "./internal";
import { Account } from "@ainblockchain/ain-util";
import { AinWalletSigner } from "@ainblockchain/ain-js/lib/signer/ain-wallet-signer";

export default class Ainize {
private cache: NodeCache;
Expand Down Expand Up @@ -39,14 +40,23 @@ export default class Ainize {
async login(privateKey: string) {
this.ain.setDefaultAccount(privateKey);
await this.handler.connect();
console.log('login success! address:', this.ain.getAddress());
console.log('login success! address:', await this.ain.getAddress());
}

/**
* Login to ainize using AIN Wallet Signer.
*/
async loginWithSigner() {
const signer = new AinWalletSigner;
this.ain.setSigner(signer);
console.log('login success! address: ', await this.ain.getAddress());
}

/**
* Logout from ainize.
*/
async logout() {
this.ain.removeDefaultAccount();
this.ain.removeSigner();
await this.handler.disconnect();
console.log('logout success!');
}
Expand All @@ -56,7 +66,7 @@ export default class Ainize {
}

async getAinBalance(): Promise<number> {
return await this.ain.getBalance();
return await this.ain.getBalance() || 0;
}

// FIXME(yoojin): add config type and change param type.
Expand All @@ -67,12 +77,9 @@ export default class Ainize {
*/
// TODO(yoojin, woojae): Deploy container, advanced.
async deploy({serviceName, billingConfig, serviceUrl}: deployConfig): Promise<Service> {
if(!this.ain.isDefaultAccountExist()) {
throw new Error('you should login first');
}
// TODO(yoojin, woojae): Add container deploy logic.
const result = await new Promise(async (resolve, reject) => {
const deployer = this.ain.getAddress();
const deployer = await this.ain.getAddress();
if (!billingConfig) {
billingConfig = {
...DEFAULT_BILLING_CONFIG,
Expand All @@ -83,6 +90,7 @@ export default class Ainize {
if (!serviceUrl) {
serviceUrl = `https://${serviceName}.ainetwork.xyz`;
}
serviceUrl = serviceUrl.replace(/\/$/, '');
const servicePath = Path.app(serviceName).status();
await this.handler.subscribe(servicePath, resolve);
await this.appController.createApp({ appName: serviceName, serviceUrl, billingConfig });
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/appController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default class AppController {
}

async checkCostAndBalance(appName: string, value: string) {
const requesterAddress = this.ain.getAddress();
const requesterAddress = await this.ain.getAddress();
const billingConfig = (await this.getBillingConfig(appName));
const token = value.split(' ').length;
let cost = token * billingConfig.costPerToken;
Expand Down
23 changes: 12 additions & 11 deletions src/controllers/serviceController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ export default class ServiceController {
}

async chargeCredit(serviceName: string, amount: number): Promise<string> {
this.checkRunning(serviceName);
await this.checkRunning(serviceName);
const transferKey = Date.now();
const userAddress = this.ain.getAddress();
const userAddress = await this.ain.getAddress();
const depositAddress = await this.getDepositAddress(serviceName);
const op_list: SetOperation[] = [
getTransferOp(userAddress, depositAddress, transferKey.toString(), amount),
Expand All @@ -66,13 +66,13 @@ export default class ServiceController {
}

async getCreditBalance(serviceName: string): Promise<number> {
const userAddress = this.ain.getAddress();
const userAddress = await this.ain.getAddress();
const balancePath = Path.app(serviceName).balanceOfUser(userAddress);
return await this.ain.getValue(balancePath) as number | 0;
}

async getCreditHistory(serviceName: string): Promise<creditHistories> {
const userAddress = this.ain.getAddress();
const userAddress = await this.ain.getAddress();
const creditHistoryPath = Path.app(serviceName).historyOfUser(userAddress);
return await this.ain.getValue(creditHistoryPath) as creditHistories;
}
Expand All @@ -82,7 +82,7 @@ export default class ServiceController {
const result = await new Promise(async (resolve, reject) => {
requestKey = requestKey || Date.now().toString();
try {
const requesterAddress = this.ain.getAddress();
const requesterAddress = await this.ain.getAddress();
const responsePath = Path.app(serviceName).response(requesterAddress, requestKey.toString());
await this.handler.subscribe(responsePath, resolve);
const requestPath = Path.app(serviceName).request(requesterAddress, requestKey);
Expand Down Expand Up @@ -120,17 +120,18 @@ export default class ServiceController {
return (await this.ain.getValue(Path.app(serviceName).billingConfig())).depositAddress;
}

isLoggedIn(): void {
if(!this.ain.getDefaultAccount())
throw new Error('You should login First.');
checkLoggedIn(): void {
if (!this.ain.isAccountSetUp()) {
throw new Error('You should login first.');
}
}

async isAdmin(serviceName: string): Promise<void> {
this.isLoggedIn();
this.checkLoggedIn();
const adminPath = `/manage_app/${serviceName}/config/admin`;
const adminList = await this.ain.getValue(adminPath);
if(!adminList[this.ain.getAddress()]) {
throw new Error('You are not admin');
if(!adminList[(await this.ain.getAddress())]) {
throw new Error('You are not a service admin.');
}
}
}
4 changes: 2 additions & 2 deletions src/handlers/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default class Handler {
}

private async disconnectedCb() {
if(AinModule.getInstance().isDefaultAccountExist()) {
if(await AinModule.getInstance().getAddress()) {
console.log('disconnected. reconnecting...');
await this.connect();
}
Expand All @@ -49,7 +49,7 @@ export default class Handler {
},
(valueChangedEvent: any) => {
this.unsubscribe(subscribeId);
resolve(valueChangedEvent.values.after.data);
resolve(valueChangedEvent.values.after);
},
(err) => {
throw new Error(err.message);
Expand Down
23 changes: 3 additions & 20 deletions src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getChangeBalanceOp, getResponseOp, getWriteHistoryOp } from "./utils/op
import { HISTORY_TYPE, RESPONSE_STATUS, deposit, request, response } from "./types/type";
import { buildTxBody } from "./utils/builder";
import AinModule from "./ain";
import { extractDataFromDepositRequest, extractDataFromServiceRequest } from "./utils/extractor";

export default class Internal {
private ain = AinModule.getInstance();
Expand Down Expand Up @@ -35,28 +36,10 @@ export default class Internal {
}

getDataFromServiceRequest(req: Request) {
if(!req.body.valuePath[1] || !req.body.valuePath[3] || !req.body.valuePath[4] || !req.body.value) {
throw new Error("Not from service request");
}
const requestData: request = {
appName: req.body.valuePath[1],
requesterAddress: req.body.auth.addr,
requestKey: req.body.valuePath[4],
requestData: req.body.value,
}
return requestData;
return extractDataFromServiceRequest(req);
}

private getDataFromDepositRequest(req: Request) {
if(!req.body.valuePath[1] || !req.body.valuePath[4] || !req.body.value) {
throw new Error("Not from deposit request");
}
const depositData: deposit = {
transferKey: req.body.valuePath[4],
transferValue: req.body.value,
appName: req.body.valuePath[1],
requesterAddress: req.body.auth.addr,
}
return depositData;
return extractDataFromDepositRequest(req);
}
}
Loading
Loading