-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d7e324d
commit 240d4b8
Showing
2 changed files
with
188 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate" | ||
import { Account, accountFromAny, SequenceResponse } from "@cosmjs/stargate" | ||
import { NibiCosmWasmClient } from "./cosmwasmclient" | ||
import { Any } from "cosmjs-types/google/protobuf/any" | ||
|
||
// Mock dependencies | ||
jest.mock("@cosmjs/cosmwasm-stargate") | ||
jest.mock("@cosmjs/stargate") | ||
jest.mock("@cosmjs/tendermint-rpc") | ||
|
||
describe("NibiCosmWasmClient", () => { | ||
const mockCosmWasmClient = { | ||
forceGetQueryClient: jest.fn(), | ||
connect: jest.fn(), | ||
} | ||
|
||
const mockQueryClient = { | ||
auth: { | ||
account: jest.fn(), | ||
}, | ||
} | ||
|
||
// Mock Any type (used for accountFromAny) | ||
const mockAny: Any = { | ||
typeUrl: "/cosmos.auth.v1beta1.BaseAccount", | ||
value: new Uint8Array([10, 20, 30, 40]), // Example value | ||
} | ||
|
||
// Mock Account structure (returned from accountFromAny) | ||
const mockAccount: Account = { | ||
address: "nibi1234...", | ||
pubkey: { | ||
type: "tendermint/PubKeySecp256k1", | ||
value: new Uint8Array([1, 2, 3, 4, 5]), | ||
}, | ||
accountNumber: 1, | ||
sequence: 1, | ||
} | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks() | ||
// Set up mock client | ||
;(CosmWasmClient.connect as jest.Mock).mockResolvedValue(mockCosmWasmClient) | ||
mockCosmWasmClient.forceGetQueryClient.mockReturnValue(mockQueryClient) | ||
}) | ||
|
||
describe("connect", () => { | ||
it("should create a new NibiCosmWasmClient", async () => { | ||
const endpoint = "http://localhost:26657" | ||
const client = await NibiCosmWasmClient.connect(endpoint) | ||
|
||
expect(CosmWasmClient.connect).toHaveBeenCalledWith(endpoint) | ||
expect(client).toBeInstanceOf(NibiCosmWasmClient) | ||
}) | ||
}) | ||
|
||
describe("getAccount", () => { | ||
it("should return parsed account if account exists", async () => { | ||
mockQueryClient.auth.account.mockResolvedValue(mockAny) | ||
// Mock accountFromAny to return the mockAccount when called with mockAny | ||
;(accountFromAny as jest.Mock).mockReturnValue(mockAccount) | ||
|
||
const client = await NibiCosmWasmClient.connect("http://localhost:26657") | ||
const result = await client.getAccount("nibi1234...") | ||
|
||
expect(mockQueryClient.auth.account).toHaveBeenCalledWith("nibi1234...") | ||
expect(result).toEqual(mockAccount) | ||
}) | ||
|
||
it("should return null if account does not exist", async () => { | ||
mockQueryClient.auth.account.mockResolvedValue(null) | ||
|
||
const client = await NibiCosmWasmClient.connect("http://localhost:26657") | ||
const result = await client.getAccount("nibi1234...") | ||
|
||
expect(mockQueryClient.auth.account).toHaveBeenCalledWith("nibi1234...") | ||
expect(result).toBeNull() | ||
}) | ||
|
||
it("should return null on 'NotFound' error", async () => { | ||
mockQueryClient.auth.account.mockRejectedValue( | ||
new Error("rpc error: code = NotFound") | ||
) | ||
|
||
const client = await NibiCosmWasmClient.connect("http://localhost:26657") | ||
const result = await client.getAccount("nibi1234...") | ||
|
||
expect(result).toBeNull() | ||
}) | ||
|
||
it("should throw error on other errors", async () => { | ||
const errorMessage = "Some other error" | ||
mockQueryClient.auth.account.mockRejectedValue(new Error(errorMessage)) | ||
|
||
const client = await NibiCosmWasmClient.connect("http://localhost:26657") | ||
await expect(client.getAccount("nibi1234...")).rejects.toThrow( | ||
errorMessage | ||
) | ||
}) | ||
}) | ||
|
||
describe("getSequence", () => { | ||
it("should return sequence and account number for valid account", async () => { | ||
mockQueryClient.auth.account.mockResolvedValue(mockAny) | ||
;(accountFromAny as jest.Mock).mockReturnValue(mockAccount) | ||
|
||
const client = await NibiCosmWasmClient.connect("http://localhost:26657") | ||
const result: SequenceResponse = await client.getSequence("nibi1234...") | ||
|
||
expect(mockQueryClient.auth.account).toHaveBeenCalledWith("nibi1234...") | ||
expect(result).toEqual({ | ||
accountNumber: mockAccount.accountNumber, | ||
sequence: mockAccount.sequence, | ||
}) | ||
}) | ||
|
||
it("should throw an error if the account does not exist", async () => { | ||
mockQueryClient.auth.account.mockResolvedValue(null) | ||
|
||
const client = await NibiCosmWasmClient.connect("http://localhost:26657") | ||
await expect(client.getSequence("nibi1234...")).rejects.toThrow( | ||
"Account 'nibi1234...' does not exist on chain. Send some tokens there before trying to query sequence." | ||
) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate" | ||
import { | ||
Account, | ||
accountFromAny, | ||
AccountParser, | ||
HttpEndpoint, | ||
SequenceResponse, | ||
} from "@cosmjs/stargate" | ||
import { CometClient } from "@cosmjs/tendermint-rpc" | ||
|
||
export interface NibiCosmWasmClientOptions { | ||
readonly accountParser?: AccountParser | ||
} | ||
|
||
export class NibiCosmWasmClient extends CosmWasmClient { | ||
private readonly accountParser: AccountParser | ||
|
||
protected constructor( | ||
cometClient: CometClient | undefined, | ||
options: NibiCosmWasmClientOptions = {} | ||
) { | ||
super(cometClient) | ||
const { accountParser = accountFromAny } = options | ||
this.accountParser = accountParser | ||
} | ||
|
||
public static async connect( | ||
endpoint: string | HttpEndpoint, | ||
options: NibiCosmWasmClientOptions = {} | ||
): Promise<NibiCosmWasmClient> { | ||
const cosmWasmClient = await CosmWasmClient.connect(endpoint) | ||
return new NibiCosmWasmClient(cosmWasmClient["cometClient"], options) | ||
} | ||
|
||
public async getAccount(searchAddress: string): Promise<Account | null> { | ||
try { | ||
const account = await this.forceGetQueryClient().auth.account( | ||
searchAddress | ||
) | ||
return account ? this.accountParser(account) : null | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
} catch (error: any) { | ||
if (/rpc error: code = NotFound/i.test(error.toString())) { | ||
return null | ||
} | ||
throw error | ||
} | ||
} | ||
|
||
public async getSequence(address: string): Promise<SequenceResponse> { | ||
const account = await this.getAccount(address) | ||
if (!account) { | ||
throw new Error( | ||
`Account '${address}' does not exist on chain. Send some tokens there before trying to query sequence.` | ||
) | ||
} | ||
return { | ||
accountNumber: account.accountNumber, | ||
sequence: account.sequence, | ||
} | ||
} | ||
} |