@agether/sdk 1.3.0 → 1.4.1
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/dist/index.d.mts +92 -13
- package/dist/index.d.ts +92 -13
- package/dist/index.js +211 -2
- package/dist/index.mjs +211 -2
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -776,29 +776,28 @@ declare class X402Client {
|
|
|
776
776
|
/**
|
|
777
777
|
* MorphoCreditClient — SDK client for Morpho-backed overcollateralized credit
|
|
778
778
|
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
* 7. Sponsor agent by address, no borrow
|
|
787
|
-
* 8. Borrow against existing collateral (for x402 payments)
|
|
788
|
-
* 9. (Handled by X402Client.autoDraw)
|
|
779
|
+
* Full lifecycle for AI agents:
|
|
780
|
+
* - Register (ERC-8004 + AccountFactory)
|
|
781
|
+
* - Check balances and status
|
|
782
|
+
* - Deposit collateral + borrow USDC
|
|
783
|
+
* - Repay debt + withdraw collateral
|
|
784
|
+
* - Sponsor another agent
|
|
785
|
+
* - Fund AgentAccount
|
|
789
786
|
*/
|
|
790
787
|
interface MorphoCreditConfig {
|
|
791
788
|
/** Private key for signing */
|
|
792
789
|
privateKey: string;
|
|
793
790
|
/** Base RPC URL */
|
|
794
791
|
rpcUrl: string;
|
|
795
|
-
/** Agent's ERC-8004 ID */
|
|
796
|
-
agentId
|
|
792
|
+
/** Agent's ERC-8004 ID (optional — auto-resolved from chain if omitted) */
|
|
793
|
+
agentId?: string | bigint;
|
|
797
794
|
/** Contract addresses */
|
|
798
795
|
contracts: {
|
|
799
796
|
morphoCredit: string;
|
|
800
797
|
accountFactory: string;
|
|
801
798
|
usdc: string;
|
|
799
|
+
/** ERC-8004 identity registry (needed for register()) */
|
|
800
|
+
agentRegistry?: string;
|
|
802
801
|
};
|
|
803
802
|
}
|
|
804
803
|
interface CollateralToken {
|
|
@@ -863,15 +862,64 @@ interface WithdrawResult {
|
|
|
863
862
|
destination: string;
|
|
864
863
|
remainingCollateral: bigint;
|
|
865
864
|
}
|
|
865
|
+
interface RegisterResult {
|
|
866
|
+
tx: string;
|
|
867
|
+
agentId: string;
|
|
868
|
+
address: string;
|
|
869
|
+
agentAccount: string;
|
|
870
|
+
alreadyRegistered: boolean;
|
|
871
|
+
}
|
|
872
|
+
interface BalancesResult {
|
|
873
|
+
address: string;
|
|
874
|
+
agentId: string;
|
|
875
|
+
eth: string;
|
|
876
|
+
usdc: string;
|
|
877
|
+
agentAccount?: {
|
|
878
|
+
address: string;
|
|
879
|
+
eth: string;
|
|
880
|
+
usdc: string;
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
interface StatusResult {
|
|
884
|
+
agentAccount: string;
|
|
885
|
+
totalDebt: string;
|
|
886
|
+
positions: Array<{
|
|
887
|
+
token: string;
|
|
888
|
+
collateral: string;
|
|
889
|
+
debt: string;
|
|
890
|
+
active: boolean;
|
|
891
|
+
}>;
|
|
892
|
+
}
|
|
893
|
+
interface FundResult {
|
|
894
|
+
tx: string;
|
|
895
|
+
amount: string;
|
|
896
|
+
agentAccount: string;
|
|
897
|
+
}
|
|
898
|
+
interface LtvCheckResult {
|
|
899
|
+
ok: boolean;
|
|
900
|
+
currentLtv: number;
|
|
901
|
+
newLtv: number;
|
|
902
|
+
maxLtv: number;
|
|
903
|
+
collateralUsd: number;
|
|
904
|
+
currentDebt: number;
|
|
905
|
+
maxBorrow: number;
|
|
906
|
+
message?: string;
|
|
907
|
+
}
|
|
866
908
|
declare class MorphoCreditClient {
|
|
867
909
|
private signer;
|
|
868
910
|
private config;
|
|
869
911
|
private morpho;
|
|
870
912
|
private factory;
|
|
871
913
|
private accountAddress?;
|
|
914
|
+
private resolvedAgentId?;
|
|
872
915
|
private collaterals;
|
|
916
|
+
private static readonly ERC8004_ABI;
|
|
873
917
|
constructor(config: MorphoCreditConfig, collaterals?: Record<string, CollateralToken>);
|
|
874
918
|
private resolveToken;
|
|
919
|
+
/**
|
|
920
|
+
* Get agentId from config or cache. Call register() first if not set.
|
|
921
|
+
*/
|
|
922
|
+
getAgentId(): Promise<string>;
|
|
875
923
|
/**
|
|
876
924
|
* Get the AgentAccount address for the configured agentId.
|
|
877
925
|
*/
|
|
@@ -894,6 +942,37 @@ declare class MorphoCreditClient {
|
|
|
894
942
|
* Each call is { target, value, data }.
|
|
895
943
|
*/
|
|
896
944
|
private batch;
|
|
945
|
+
/**
|
|
946
|
+
* Register a new ERC-8004 agent identity and create an AgentAccount.
|
|
947
|
+
* If already registered (agentId in config or on-chain), returns existing info.
|
|
948
|
+
*
|
|
949
|
+
* @param name - Agent display name
|
|
950
|
+
*/
|
|
951
|
+
register(name: string): Promise<RegisterResult>;
|
|
952
|
+
/**
|
|
953
|
+
* Get ETH and USDC balances for EOA wallet and AgentAccount.
|
|
954
|
+
*/
|
|
955
|
+
getBalances(): Promise<BalancesResult>;
|
|
956
|
+
/**
|
|
957
|
+
* Get full Morpho credit status — all positions + total debt.
|
|
958
|
+
*/
|
|
959
|
+
getStatus(): Promise<StatusResult>;
|
|
960
|
+
/**
|
|
961
|
+
* Transfer USDC from EOA wallet into AgentAccount.
|
|
962
|
+
*
|
|
963
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
964
|
+
*/
|
|
965
|
+
fundAccount(amount: string): Promise<FundResult>;
|
|
966
|
+
private static readonly ORACLE_ABI;
|
|
967
|
+
/**
|
|
968
|
+
* Check whether a borrow would exceed max LTV.
|
|
969
|
+
* Call before borrow() or depositAndBorrow() to get a clear error instead of on-chain revert.
|
|
970
|
+
*
|
|
971
|
+
* @param tokenSymbol - Collateral token
|
|
972
|
+
* @param additionalCollateral - Additional collateral being deposited ("0" if just borrowing)
|
|
973
|
+
* @param borrowAmount - USDC to borrow
|
|
974
|
+
*/
|
|
975
|
+
checkLtv(tokenSymbol: string, additionalCollateral: string, borrowAmount: string): Promise<LtvCheckResult>;
|
|
897
976
|
/**
|
|
898
977
|
* Deposit collateral from EOA into Morpho for own AgentAccount.
|
|
899
978
|
* Does NOT borrow — use `borrow()` or `depositAndBorrow()` for that.
|
|
@@ -1134,4 +1213,4 @@ declare const VALIDATION_REGISTRY_ABI: string[];
|
|
|
1134
1213
|
declare const MORPHO_CREDIT_ABI: string[];
|
|
1135
1214
|
declare const ERC20_ABI: string[];
|
|
1136
1215
|
|
|
1137
|
-
export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, type AgentReputation, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BayesianScore, type BorrowResult, CREDIT_PROVIDER_ABI, ChainId, type CollateralToken, type ContractAddresses, type CreditApplication, type CreditAppliedEvent, type CreditApprovedEvent, type CreditDrawnEvent, type CreditInfo, type CreditLine, CreditNotActiveError, type CreditRejectedEvent, type CreditRepaidEvent, CreditStatus, type DepositAndBorrowResult, type DepositResult, type DrawRequest, ERC20_ABI, type GraduationStatus, IDENTITY_REGISTRY_ABI, InsufficientCreditError, type LPPosition, LP_VAULT_ABI, type LoanPosition, MORPHO_CREDIT_ABI, MorphoCreditClient, type MorphoCreditConfig, type MorphoMarketParams, type MorphoPosition, type PaymentProof, type PaymentRequirements, type ProviderStatus, REPUTATION_CREDIT_ABI, type RepayRequest, type RepayResult, type RiskCheckResponse, type RiskFactor, type ScoreExplanation, type ScoredLimitPreview, ScoringClient, type ScoringContext, ScoringRejectedError, type ScoringRequest, type ScoringResult, type SponsorResult, type TransactionResult, VALIDATION_REGISTRY_ABI, VaultClient, type VaultClientOptions, type VaultStats, WalletClient, type WalletClientConfig, type WalletInfo, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, getUSDCAddress, parseUnits, rateToBps };
|
|
1216
|
+
export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, type AgentReputation, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BalancesResult, type BayesianScore, type BorrowResult, CREDIT_PROVIDER_ABI, ChainId, type CollateralToken, type ContractAddresses, type CreditApplication, type CreditAppliedEvent, type CreditApprovedEvent, type CreditDrawnEvent, type CreditInfo, type CreditLine, CreditNotActiveError, type CreditRejectedEvent, type CreditRepaidEvent, CreditStatus, type DepositAndBorrowResult, type DepositResult, type DrawRequest, ERC20_ABI, type FundResult, type GraduationStatus, IDENTITY_REGISTRY_ABI, InsufficientCreditError, type LPPosition, LP_VAULT_ABI, type LoanPosition, type LtvCheckResult, MORPHO_CREDIT_ABI, MorphoCreditClient, type MorphoCreditConfig, type MorphoMarketParams, type MorphoPosition, type PaymentProof, type PaymentRequirements, type ProviderStatus, REPUTATION_CREDIT_ABI, type RegisterResult, type RepayRequest, type RepayResult, type RiskCheckResponse, type RiskFactor, type ScoreExplanation, type ScoredLimitPreview, ScoringClient, type ScoringContext, ScoringRejectedError, type ScoringRequest, type ScoringResult, type SponsorResult, type StatusResult, type TransactionResult, VALIDATION_REGISTRY_ABI, VaultClient, type VaultClientOptions, type VaultStats, WalletClient, type WalletClientConfig, type WalletInfo, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, getUSDCAddress, parseUnits, rateToBps };
|
package/dist/index.d.ts
CHANGED
|
@@ -776,29 +776,28 @@ declare class X402Client {
|
|
|
776
776
|
/**
|
|
777
777
|
* MorphoCreditClient — SDK client for Morpho-backed overcollateralized credit
|
|
778
778
|
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
* 7. Sponsor agent by address, no borrow
|
|
787
|
-
* 8. Borrow against existing collateral (for x402 payments)
|
|
788
|
-
* 9. (Handled by X402Client.autoDraw)
|
|
779
|
+
* Full lifecycle for AI agents:
|
|
780
|
+
* - Register (ERC-8004 + AccountFactory)
|
|
781
|
+
* - Check balances and status
|
|
782
|
+
* - Deposit collateral + borrow USDC
|
|
783
|
+
* - Repay debt + withdraw collateral
|
|
784
|
+
* - Sponsor another agent
|
|
785
|
+
* - Fund AgentAccount
|
|
789
786
|
*/
|
|
790
787
|
interface MorphoCreditConfig {
|
|
791
788
|
/** Private key for signing */
|
|
792
789
|
privateKey: string;
|
|
793
790
|
/** Base RPC URL */
|
|
794
791
|
rpcUrl: string;
|
|
795
|
-
/** Agent's ERC-8004 ID */
|
|
796
|
-
agentId
|
|
792
|
+
/** Agent's ERC-8004 ID (optional — auto-resolved from chain if omitted) */
|
|
793
|
+
agentId?: string | bigint;
|
|
797
794
|
/** Contract addresses */
|
|
798
795
|
contracts: {
|
|
799
796
|
morphoCredit: string;
|
|
800
797
|
accountFactory: string;
|
|
801
798
|
usdc: string;
|
|
799
|
+
/** ERC-8004 identity registry (needed for register()) */
|
|
800
|
+
agentRegistry?: string;
|
|
802
801
|
};
|
|
803
802
|
}
|
|
804
803
|
interface CollateralToken {
|
|
@@ -863,15 +862,64 @@ interface WithdrawResult {
|
|
|
863
862
|
destination: string;
|
|
864
863
|
remainingCollateral: bigint;
|
|
865
864
|
}
|
|
865
|
+
interface RegisterResult {
|
|
866
|
+
tx: string;
|
|
867
|
+
agentId: string;
|
|
868
|
+
address: string;
|
|
869
|
+
agentAccount: string;
|
|
870
|
+
alreadyRegistered: boolean;
|
|
871
|
+
}
|
|
872
|
+
interface BalancesResult {
|
|
873
|
+
address: string;
|
|
874
|
+
agentId: string;
|
|
875
|
+
eth: string;
|
|
876
|
+
usdc: string;
|
|
877
|
+
agentAccount?: {
|
|
878
|
+
address: string;
|
|
879
|
+
eth: string;
|
|
880
|
+
usdc: string;
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
interface StatusResult {
|
|
884
|
+
agentAccount: string;
|
|
885
|
+
totalDebt: string;
|
|
886
|
+
positions: Array<{
|
|
887
|
+
token: string;
|
|
888
|
+
collateral: string;
|
|
889
|
+
debt: string;
|
|
890
|
+
active: boolean;
|
|
891
|
+
}>;
|
|
892
|
+
}
|
|
893
|
+
interface FundResult {
|
|
894
|
+
tx: string;
|
|
895
|
+
amount: string;
|
|
896
|
+
agentAccount: string;
|
|
897
|
+
}
|
|
898
|
+
interface LtvCheckResult {
|
|
899
|
+
ok: boolean;
|
|
900
|
+
currentLtv: number;
|
|
901
|
+
newLtv: number;
|
|
902
|
+
maxLtv: number;
|
|
903
|
+
collateralUsd: number;
|
|
904
|
+
currentDebt: number;
|
|
905
|
+
maxBorrow: number;
|
|
906
|
+
message?: string;
|
|
907
|
+
}
|
|
866
908
|
declare class MorphoCreditClient {
|
|
867
909
|
private signer;
|
|
868
910
|
private config;
|
|
869
911
|
private morpho;
|
|
870
912
|
private factory;
|
|
871
913
|
private accountAddress?;
|
|
914
|
+
private resolvedAgentId?;
|
|
872
915
|
private collaterals;
|
|
916
|
+
private static readonly ERC8004_ABI;
|
|
873
917
|
constructor(config: MorphoCreditConfig, collaterals?: Record<string, CollateralToken>);
|
|
874
918
|
private resolveToken;
|
|
919
|
+
/**
|
|
920
|
+
* Get agentId from config or cache. Call register() first if not set.
|
|
921
|
+
*/
|
|
922
|
+
getAgentId(): Promise<string>;
|
|
875
923
|
/**
|
|
876
924
|
* Get the AgentAccount address for the configured agentId.
|
|
877
925
|
*/
|
|
@@ -894,6 +942,37 @@ declare class MorphoCreditClient {
|
|
|
894
942
|
* Each call is { target, value, data }.
|
|
895
943
|
*/
|
|
896
944
|
private batch;
|
|
945
|
+
/**
|
|
946
|
+
* Register a new ERC-8004 agent identity and create an AgentAccount.
|
|
947
|
+
* If already registered (agentId in config or on-chain), returns existing info.
|
|
948
|
+
*
|
|
949
|
+
* @param name - Agent display name
|
|
950
|
+
*/
|
|
951
|
+
register(name: string): Promise<RegisterResult>;
|
|
952
|
+
/**
|
|
953
|
+
* Get ETH and USDC balances for EOA wallet and AgentAccount.
|
|
954
|
+
*/
|
|
955
|
+
getBalances(): Promise<BalancesResult>;
|
|
956
|
+
/**
|
|
957
|
+
* Get full Morpho credit status — all positions + total debt.
|
|
958
|
+
*/
|
|
959
|
+
getStatus(): Promise<StatusResult>;
|
|
960
|
+
/**
|
|
961
|
+
* Transfer USDC from EOA wallet into AgentAccount.
|
|
962
|
+
*
|
|
963
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
964
|
+
*/
|
|
965
|
+
fundAccount(amount: string): Promise<FundResult>;
|
|
966
|
+
private static readonly ORACLE_ABI;
|
|
967
|
+
/**
|
|
968
|
+
* Check whether a borrow would exceed max LTV.
|
|
969
|
+
* Call before borrow() or depositAndBorrow() to get a clear error instead of on-chain revert.
|
|
970
|
+
*
|
|
971
|
+
* @param tokenSymbol - Collateral token
|
|
972
|
+
* @param additionalCollateral - Additional collateral being deposited ("0" if just borrowing)
|
|
973
|
+
* @param borrowAmount - USDC to borrow
|
|
974
|
+
*/
|
|
975
|
+
checkLtv(tokenSymbol: string, additionalCollateral: string, borrowAmount: string): Promise<LtvCheckResult>;
|
|
897
976
|
/**
|
|
898
977
|
* Deposit collateral from EOA into Morpho for own AgentAccount.
|
|
899
978
|
* Does NOT borrow — use `borrow()` or `depositAndBorrow()` for that.
|
|
@@ -1134,4 +1213,4 @@ declare const VALIDATION_REGISTRY_ABI: string[];
|
|
|
1134
1213
|
declare const MORPHO_CREDIT_ABI: string[];
|
|
1135
1214
|
declare const ERC20_ABI: string[];
|
|
1136
1215
|
|
|
1137
|
-
export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, type AgentReputation, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BayesianScore, type BorrowResult, CREDIT_PROVIDER_ABI, ChainId, type CollateralToken, type ContractAddresses, type CreditApplication, type CreditAppliedEvent, type CreditApprovedEvent, type CreditDrawnEvent, type CreditInfo, type CreditLine, CreditNotActiveError, type CreditRejectedEvent, type CreditRepaidEvent, CreditStatus, type DepositAndBorrowResult, type DepositResult, type DrawRequest, ERC20_ABI, type GraduationStatus, IDENTITY_REGISTRY_ABI, InsufficientCreditError, type LPPosition, LP_VAULT_ABI, type LoanPosition, MORPHO_CREDIT_ABI, MorphoCreditClient, type MorphoCreditConfig, type MorphoMarketParams, type MorphoPosition, type PaymentProof, type PaymentRequirements, type ProviderStatus, REPUTATION_CREDIT_ABI, type RepayRequest, type RepayResult, type RiskCheckResponse, type RiskFactor, type ScoreExplanation, type ScoredLimitPreview, ScoringClient, type ScoringContext, ScoringRejectedError, type ScoringRequest, type ScoringResult, type SponsorResult, type TransactionResult, VALIDATION_REGISTRY_ABI, VaultClient, type VaultClientOptions, type VaultStats, WalletClient, type WalletClientConfig, type WalletInfo, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, getUSDCAddress, parseUnits, rateToBps };
|
|
1216
|
+
export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, type AgentReputation, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BalancesResult, type BayesianScore, type BorrowResult, CREDIT_PROVIDER_ABI, ChainId, type CollateralToken, type ContractAddresses, type CreditApplication, type CreditAppliedEvent, type CreditApprovedEvent, type CreditDrawnEvent, type CreditInfo, type CreditLine, CreditNotActiveError, type CreditRejectedEvent, type CreditRepaidEvent, CreditStatus, type DepositAndBorrowResult, type DepositResult, type DrawRequest, ERC20_ABI, type FundResult, type GraduationStatus, IDENTITY_REGISTRY_ABI, InsufficientCreditError, type LPPosition, LP_VAULT_ABI, type LoanPosition, type LtvCheckResult, MORPHO_CREDIT_ABI, MorphoCreditClient, type MorphoCreditConfig, type MorphoMarketParams, type MorphoPosition, type PaymentProof, type PaymentRequirements, type ProviderStatus, REPUTATION_CREDIT_ABI, type RegisterResult, type RepayRequest, type RepayResult, type RiskCheckResponse, type RiskFactor, type ScoreExplanation, type ScoredLimitPreview, ScoringClient, type ScoringContext, ScoringRejectedError, type ScoringRequest, type ScoringResult, type SponsorResult, type StatusResult, type TransactionResult, VALIDATION_REGISTRY_ABI, VaultClient, type VaultClientOptions, type VaultStats, WalletClient, type WalletClientConfig, type WalletInfo, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, getUSDCAddress, parseUnits, rateToBps };
|
package/dist/index.js
CHANGED
|
@@ -1510,7 +1510,7 @@ var BASE_COLLATERALS = {
|
|
|
1510
1510
|
wstETH: { symbol: "wstETH", address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", decimals: 18 },
|
|
1511
1511
|
cbETH: { symbol: "cbETH", address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", decimals: 18 }
|
|
1512
1512
|
};
|
|
1513
|
-
var
|
|
1513
|
+
var _MorphoCreditClient = class _MorphoCreditClient {
|
|
1514
1514
|
constructor(config, collaterals) {
|
|
1515
1515
|
// ── Batch helper ──
|
|
1516
1516
|
this.morphoIface = new import_ethers5.ethers.Interface(MORPHO_CREDIT_ABI);
|
|
@@ -1521,6 +1521,7 @@ var MorphoCreditClient = class {
|
|
|
1521
1521
|
this.morpho = new import_ethers5.Contract(config.contracts.morphoCredit, MORPHO_CREDIT_ABI, this.signer);
|
|
1522
1522
|
this.factory = new import_ethers5.Contract(config.contracts.accountFactory, ACCOUNT_FACTORY_ABI, this.signer);
|
|
1523
1523
|
this.collaterals = collaterals || BASE_COLLATERALS;
|
|
1524
|
+
if (config.agentId) this.resolvedAgentId = config.agentId.toString();
|
|
1524
1525
|
}
|
|
1525
1526
|
// ── Helpers ──
|
|
1526
1527
|
resolveToken(tokenSymbol) {
|
|
@@ -1530,12 +1531,20 @@ var MorphoCreditClient = class {
|
|
|
1530
1531
|
}
|
|
1531
1532
|
return token;
|
|
1532
1533
|
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Get agentId from config or cache. Call register() first if not set.
|
|
1536
|
+
*/
|
|
1537
|
+
async getAgentId() {
|
|
1538
|
+
if (this.resolvedAgentId) return this.resolvedAgentId;
|
|
1539
|
+
throw new Error("No agentId. Pass agentId in config or call register() first.");
|
|
1540
|
+
}
|
|
1533
1541
|
/**
|
|
1534
1542
|
* Get the AgentAccount address for the configured agentId.
|
|
1535
1543
|
*/
|
|
1536
1544
|
async getAccountAddress() {
|
|
1537
1545
|
if (this.accountAddress) return this.accountAddress;
|
|
1538
|
-
const
|
|
1546
|
+
const agentId = await this.getAgentId();
|
|
1547
|
+
const addr = await this.factory.getAccount(agentId);
|
|
1539
1548
|
if (addr === import_ethers5.ethers.ZeroAddress) {
|
|
1540
1549
|
throw new Error("No AgentAccount found. Register first.");
|
|
1541
1550
|
}
|
|
@@ -1594,6 +1603,192 @@ var MorphoCreditClient = class {
|
|
|
1594
1603
|
return tx.hash;
|
|
1595
1604
|
}
|
|
1596
1605
|
// ══════════════════════════════════════════
|
|
1606
|
+
// Register
|
|
1607
|
+
// ══════════════════════════════════════════
|
|
1608
|
+
/**
|
|
1609
|
+
* Register a new ERC-8004 agent identity and create an AgentAccount.
|
|
1610
|
+
* If already registered (agentId in config or on-chain), returns existing info.
|
|
1611
|
+
*
|
|
1612
|
+
* @param name - Agent display name
|
|
1613
|
+
*/
|
|
1614
|
+
async register(name) {
|
|
1615
|
+
if (!this.config.contracts.agentRegistry) {
|
|
1616
|
+
throw new Error("agentRegistry address required for register()");
|
|
1617
|
+
}
|
|
1618
|
+
const registry = new import_ethers5.Contract(
|
|
1619
|
+
this.config.contracts.agentRegistry,
|
|
1620
|
+
_MorphoCreditClient.ERC8004_ABI,
|
|
1621
|
+
this.signer
|
|
1622
|
+
);
|
|
1623
|
+
if (this.resolvedAgentId) {
|
|
1624
|
+
const agentId2 = BigInt(this.resolvedAgentId);
|
|
1625
|
+
const owner = await registry.ownerOf(agentId2);
|
|
1626
|
+
if (owner.toLowerCase() !== this.signer.address.toLowerCase()) {
|
|
1627
|
+
throw new Error("agentId in config does not belong to this wallet");
|
|
1628
|
+
}
|
|
1629
|
+
const exists2 = await this.factory.accountExists(agentId2);
|
|
1630
|
+
if (!exists2) {
|
|
1631
|
+
const tx2 = await this.factory.createAccount(agentId2);
|
|
1632
|
+
await tx2.wait();
|
|
1633
|
+
}
|
|
1634
|
+
const accountAddr2 = await this.factory.getAccount(this.resolvedAgentId);
|
|
1635
|
+
return {
|
|
1636
|
+
tx: "",
|
|
1637
|
+
agentId: this.resolvedAgentId,
|
|
1638
|
+
address: this.signer.address,
|
|
1639
|
+
agentAccount: accountAddr2,
|
|
1640
|
+
alreadyRegistered: true
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
const registrationFile = JSON.stringify({
|
|
1644
|
+
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
|
|
1645
|
+
name,
|
|
1646
|
+
description: "AI agent registered via @agether/sdk",
|
|
1647
|
+
active: true,
|
|
1648
|
+
registrations: [{
|
|
1649
|
+
agentId: 0,
|
|
1650
|
+
agentRegistry: `eip155:8453:${this.config.contracts.agentRegistry}`
|
|
1651
|
+
}]
|
|
1652
|
+
});
|
|
1653
|
+
const agentURI = `data:application/json;base64,${Buffer.from(registrationFile).toString("base64")}`;
|
|
1654
|
+
const tx = await registry["register(string)"](agentURI);
|
|
1655
|
+
const receipt = await tx.wait();
|
|
1656
|
+
const transferTopic = import_ethers5.ethers.id("Transfer(address,address,uint256)");
|
|
1657
|
+
const transferLog = receipt.logs.find((l) => l.topics[0] === transferTopic);
|
|
1658
|
+
if (!transferLog?.topics?.[3]) {
|
|
1659
|
+
throw new Error("Could not parse agentId from receipt");
|
|
1660
|
+
}
|
|
1661
|
+
const agentId = BigInt(transferLog.topics[3]);
|
|
1662
|
+
this.resolvedAgentId = agentId.toString();
|
|
1663
|
+
const exists = await this.factory.accountExists(agentId);
|
|
1664
|
+
if (!exists) {
|
|
1665
|
+
const accTx = await this.factory.createAccount(agentId);
|
|
1666
|
+
await accTx.wait();
|
|
1667
|
+
}
|
|
1668
|
+
const accountAddr = await this.factory.getAccount(this.resolvedAgentId);
|
|
1669
|
+
this.accountAddress = accountAddr;
|
|
1670
|
+
return {
|
|
1671
|
+
tx: tx.hash,
|
|
1672
|
+
agentId: this.resolvedAgentId,
|
|
1673
|
+
address: this.signer.address,
|
|
1674
|
+
agentAccount: accountAddr,
|
|
1675
|
+
alreadyRegistered: false
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
// ══════════════════════════════════════════
|
|
1679
|
+
// Balances & Status
|
|
1680
|
+
// ══════════════════════════════════════════
|
|
1681
|
+
/**
|
|
1682
|
+
* Get ETH and USDC balances for EOA wallet and AgentAccount.
|
|
1683
|
+
*/
|
|
1684
|
+
async getBalances() {
|
|
1685
|
+
const provider = this.signer.provider;
|
|
1686
|
+
const ethBal = await provider.getBalance(this.signer.address);
|
|
1687
|
+
const usdc = new import_ethers5.Contract(this.config.contracts.usdc, ERC20_ABI, provider);
|
|
1688
|
+
const usdcBal = await usdc.balanceOf(this.signer.address);
|
|
1689
|
+
const result = {
|
|
1690
|
+
address: this.signer.address,
|
|
1691
|
+
agentId: this.resolvedAgentId || "not registered",
|
|
1692
|
+
eth: import_ethers5.ethers.formatEther(ethBal),
|
|
1693
|
+
usdc: import_ethers5.ethers.formatUnits(usdcBal, 6)
|
|
1694
|
+
};
|
|
1695
|
+
try {
|
|
1696
|
+
const accountAddr = await this.getAccountAddress();
|
|
1697
|
+
const accEth = await provider.getBalance(accountAddr);
|
|
1698
|
+
const accUsdc = await usdc.balanceOf(accountAddr);
|
|
1699
|
+
result.agentAccount = {
|
|
1700
|
+
address: accountAddr,
|
|
1701
|
+
eth: import_ethers5.ethers.formatEther(accEth),
|
|
1702
|
+
usdc: import_ethers5.ethers.formatUnits(accUsdc, 6)
|
|
1703
|
+
};
|
|
1704
|
+
} catch {
|
|
1705
|
+
}
|
|
1706
|
+
return result;
|
|
1707
|
+
}
|
|
1708
|
+
/**
|
|
1709
|
+
* Get full Morpho credit status — all positions + total debt.
|
|
1710
|
+
*/
|
|
1711
|
+
async getStatus() {
|
|
1712
|
+
const accountAddr = await this.getAccountAddress();
|
|
1713
|
+
const positions = [];
|
|
1714
|
+
for (const [symbol, info] of Object.entries(this.collaterals)) {
|
|
1715
|
+
const pos = await this.morpho.getPosition(accountAddr, info.address);
|
|
1716
|
+
if (pos.isActive || pos.collateralAmount > 0n || pos.borrowedAmount > 0n) {
|
|
1717
|
+
positions.push({
|
|
1718
|
+
token: symbol,
|
|
1719
|
+
collateral: import_ethers5.ethers.formatUnits(pos.collateralAmount, info.decimals),
|
|
1720
|
+
debt: `$${import_ethers5.ethers.formatUnits(pos.borrowedAmount, 6)}`,
|
|
1721
|
+
active: pos.isActive
|
|
1722
|
+
});
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1726
|
+
return {
|
|
1727
|
+
agentAccount: accountAddr,
|
|
1728
|
+
totalDebt: `$${import_ethers5.ethers.formatUnits(totalDebt, 6)}`,
|
|
1729
|
+
positions
|
|
1730
|
+
};
|
|
1731
|
+
}
|
|
1732
|
+
// ══════════════════════════════════════════
|
|
1733
|
+
// Fund AgentAccount
|
|
1734
|
+
// ══════════════════════════════════════════
|
|
1735
|
+
/**
|
|
1736
|
+
* Transfer USDC from EOA wallet into AgentAccount.
|
|
1737
|
+
*
|
|
1738
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
1739
|
+
*/
|
|
1740
|
+
async fundAccount(amount) {
|
|
1741
|
+
const amountWei = import_ethers5.ethers.parseUnits(amount, 6);
|
|
1742
|
+
const accountAddr = await this.getAccountAddress();
|
|
1743
|
+
const usdc = new import_ethers5.Contract(this.config.contracts.usdc, ERC20_ABI, this.signer);
|
|
1744
|
+
const balance = await usdc.balanceOf(this.signer.address);
|
|
1745
|
+
if (balance < amountWei) {
|
|
1746
|
+
throw new Error(`Insufficient USDC: have $${import_ethers5.ethers.formatUnits(balance, 6)}, need $${amount}`);
|
|
1747
|
+
}
|
|
1748
|
+
const tx = await usdc.transfer(accountAddr, amountWei);
|
|
1749
|
+
await tx.wait();
|
|
1750
|
+
return { tx: tx.hash, amount, agentAccount: accountAddr };
|
|
1751
|
+
}
|
|
1752
|
+
/**
|
|
1753
|
+
* Check whether a borrow would exceed max LTV.
|
|
1754
|
+
* Call before borrow() or depositAndBorrow() to get a clear error instead of on-chain revert.
|
|
1755
|
+
*
|
|
1756
|
+
* @param tokenSymbol - Collateral token
|
|
1757
|
+
* @param additionalCollateral - Additional collateral being deposited ("0" if just borrowing)
|
|
1758
|
+
* @param borrowAmount - USDC to borrow
|
|
1759
|
+
*/
|
|
1760
|
+
async checkLtv(tokenSymbol, additionalCollateral, borrowAmount) {
|
|
1761
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1762
|
+
const accountAddr = await this.getAccountAddress();
|
|
1763
|
+
const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1764
|
+
const marketInfo = await this.morpho.markets(tokenInfo.address);
|
|
1765
|
+
const oracle = new import_ethers5.Contract(marketInfo.params.oracle, _MorphoCreditClient.ORACLE_ABI, this.signer.provider);
|
|
1766
|
+
const oraclePrice = await oracle.price();
|
|
1767
|
+
const addCollateralWei = import_ethers5.ethers.parseUnits(additionalCollateral, tokenInfo.decimals);
|
|
1768
|
+
const borrowWei = import_ethers5.ethers.parseUnits(borrowAmount, 6);
|
|
1769
|
+
const totalCollateral = pos.collateralAmount + addCollateralWei;
|
|
1770
|
+
const totalDebt = pos.borrowedAmount + borrowWei;
|
|
1771
|
+
const collateralValue = totalCollateral * oraclePrice / BigInt("1000000000000000000000000000000000000");
|
|
1772
|
+
const collateralUsd = Number(collateralValue) / 1e6;
|
|
1773
|
+
const currentDebtUsd = Number(pos.borrowedAmount) / 1e6;
|
|
1774
|
+
const maxLtvBps = Number(marketInfo.maxLtvBps);
|
|
1775
|
+
const currentLtv = collateralValue > 0n ? Number(pos.borrowedAmount * 10000n / collateralValue) / 100 : 0;
|
|
1776
|
+
const newLtv = collateralValue > 0n ? Number(totalDebt * 10000n / collateralValue) / 100 : totalDebt > 0n ? Infinity : 0;
|
|
1777
|
+
const maxLtv = maxLtvBps / 100;
|
|
1778
|
+
const maxBorrow = collateralUsd * maxLtvBps / 1e4;
|
|
1779
|
+
const ok = newLtv <= maxLtv;
|
|
1780
|
+
return {
|
|
1781
|
+
ok,
|
|
1782
|
+
currentLtv,
|
|
1783
|
+
newLtv,
|
|
1784
|
+
maxLtv,
|
|
1785
|
+
collateralUsd,
|
|
1786
|
+
currentDebt: currentDebtUsd,
|
|
1787
|
+
maxBorrow,
|
|
1788
|
+
message: ok ? void 0 : `ExceedsMaxLtv: borrowing $${borrowAmount} would push LTV to ${newLtv.toFixed(1)}% (max ${maxLtv}%). Collateral: $${collateralUsd.toFixed(2)}. Current debt: $${currentDebtUsd.toFixed(3)}. Max additional borrow: $${(maxBorrow - currentDebtUsd).toFixed(2)}. Deposit more collateral or borrow less.`
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
// ══════════════════════════════════════════
|
|
1597
1792
|
// Flow 3: Deposit collateral only
|
|
1598
1793
|
// ══════════════════════════════════════════
|
|
1599
1794
|
/**
|
|
@@ -1634,6 +1829,8 @@ var MorphoCreditClient = class {
|
|
|
1634
1829
|
const collateralWei = import_ethers5.ethers.parseUnits(collateralAmount, tokenInfo.decimals);
|
|
1635
1830
|
const borrowWei = import_ethers5.ethers.parseUnits(borrowAmount, 6);
|
|
1636
1831
|
const accountAddr = await this.getAccountAddress();
|
|
1832
|
+
const ltvCheck = await this.checkLtv(tokenSymbol, collateralAmount, borrowAmount);
|
|
1833
|
+
if (!ltvCheck.ok) throw new Error(ltvCheck.message);
|
|
1637
1834
|
const depositTxHash = await this.approveAndDeposit(accountAddr, tokenInfo, collateralWei);
|
|
1638
1835
|
await this.ensureCreditProvider(accountAddr);
|
|
1639
1836
|
const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
@@ -1674,6 +1871,8 @@ var MorphoCreditClient = class {
|
|
|
1674
1871
|
if (!activeToken) {
|
|
1675
1872
|
throw new Error("No collateral deposited. Use deposit() or depositAndBorrow() first.");
|
|
1676
1873
|
}
|
|
1874
|
+
const ltvCheck = await this.checkLtv(activeToken.symbol, "0", amount);
|
|
1875
|
+
if (!ltvCheck.ok) throw new Error(ltvCheck.message);
|
|
1677
1876
|
await this.ensureCreditProvider(accountAddr);
|
|
1678
1877
|
const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1679
1878
|
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [activeToken.address, borrowWei]);
|
|
@@ -1879,6 +2078,16 @@ var MorphoCreditClient = class {
|
|
|
1879
2078
|
return this.signer.address;
|
|
1880
2079
|
}
|
|
1881
2080
|
};
|
|
2081
|
+
_MorphoCreditClient.ERC8004_ABI = [
|
|
2082
|
+
"function register(string agentURI) returns (uint256)",
|
|
2083
|
+
"function ownerOf(uint256 tokenId) view returns (address)",
|
|
2084
|
+
"function balanceOf(address owner) view returns (uint256)"
|
|
2085
|
+
];
|
|
2086
|
+
// ══════════════════════════════════════════
|
|
2087
|
+
// LTV Pre-check
|
|
2088
|
+
// ══════════════════════════════════════════
|
|
2089
|
+
_MorphoCreditClient.ORACLE_ABI = ["function price() view returns (uint256)"];
|
|
2090
|
+
var MorphoCreditClient = _MorphoCreditClient;
|
|
1882
2091
|
|
|
1883
2092
|
// src/clients/WalletClient.ts
|
|
1884
2093
|
var import_ethers6 = require("ethers");
|
package/dist/index.mjs
CHANGED
|
@@ -1439,7 +1439,7 @@ var BASE_COLLATERALS = {
|
|
|
1439
1439
|
wstETH: { symbol: "wstETH", address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", decimals: 18 },
|
|
1440
1440
|
cbETH: { symbol: "cbETH", address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", decimals: 18 }
|
|
1441
1441
|
};
|
|
1442
|
-
var
|
|
1442
|
+
var _MorphoCreditClient = class _MorphoCreditClient {
|
|
1443
1443
|
constructor(config, collaterals) {
|
|
1444
1444
|
// ── Batch helper ──
|
|
1445
1445
|
this.morphoIface = new ethers4.Interface(MORPHO_CREDIT_ABI);
|
|
@@ -1450,6 +1450,7 @@ var MorphoCreditClient = class {
|
|
|
1450
1450
|
this.morpho = new Contract3(config.contracts.morphoCredit, MORPHO_CREDIT_ABI, this.signer);
|
|
1451
1451
|
this.factory = new Contract3(config.contracts.accountFactory, ACCOUNT_FACTORY_ABI, this.signer);
|
|
1452
1452
|
this.collaterals = collaterals || BASE_COLLATERALS;
|
|
1453
|
+
if (config.agentId) this.resolvedAgentId = config.agentId.toString();
|
|
1453
1454
|
}
|
|
1454
1455
|
// ── Helpers ──
|
|
1455
1456
|
resolveToken(tokenSymbol) {
|
|
@@ -1459,12 +1460,20 @@ var MorphoCreditClient = class {
|
|
|
1459
1460
|
}
|
|
1460
1461
|
return token;
|
|
1461
1462
|
}
|
|
1463
|
+
/**
|
|
1464
|
+
* Get agentId from config or cache. Call register() first if not set.
|
|
1465
|
+
*/
|
|
1466
|
+
async getAgentId() {
|
|
1467
|
+
if (this.resolvedAgentId) return this.resolvedAgentId;
|
|
1468
|
+
throw new Error("No agentId. Pass agentId in config or call register() first.");
|
|
1469
|
+
}
|
|
1462
1470
|
/**
|
|
1463
1471
|
* Get the AgentAccount address for the configured agentId.
|
|
1464
1472
|
*/
|
|
1465
1473
|
async getAccountAddress() {
|
|
1466
1474
|
if (this.accountAddress) return this.accountAddress;
|
|
1467
|
-
const
|
|
1475
|
+
const agentId = await this.getAgentId();
|
|
1476
|
+
const addr = await this.factory.getAccount(agentId);
|
|
1468
1477
|
if (addr === ethers4.ZeroAddress) {
|
|
1469
1478
|
throw new Error("No AgentAccount found. Register first.");
|
|
1470
1479
|
}
|
|
@@ -1523,6 +1532,192 @@ var MorphoCreditClient = class {
|
|
|
1523
1532
|
return tx.hash;
|
|
1524
1533
|
}
|
|
1525
1534
|
// ══════════════════════════════════════════
|
|
1535
|
+
// Register
|
|
1536
|
+
// ══════════════════════════════════════════
|
|
1537
|
+
/**
|
|
1538
|
+
* Register a new ERC-8004 agent identity and create an AgentAccount.
|
|
1539
|
+
* If already registered (agentId in config or on-chain), returns existing info.
|
|
1540
|
+
*
|
|
1541
|
+
* @param name - Agent display name
|
|
1542
|
+
*/
|
|
1543
|
+
async register(name) {
|
|
1544
|
+
if (!this.config.contracts.agentRegistry) {
|
|
1545
|
+
throw new Error("agentRegistry address required for register()");
|
|
1546
|
+
}
|
|
1547
|
+
const registry = new Contract3(
|
|
1548
|
+
this.config.contracts.agentRegistry,
|
|
1549
|
+
_MorphoCreditClient.ERC8004_ABI,
|
|
1550
|
+
this.signer
|
|
1551
|
+
);
|
|
1552
|
+
if (this.resolvedAgentId) {
|
|
1553
|
+
const agentId2 = BigInt(this.resolvedAgentId);
|
|
1554
|
+
const owner = await registry.ownerOf(agentId2);
|
|
1555
|
+
if (owner.toLowerCase() !== this.signer.address.toLowerCase()) {
|
|
1556
|
+
throw new Error("agentId in config does not belong to this wallet");
|
|
1557
|
+
}
|
|
1558
|
+
const exists2 = await this.factory.accountExists(agentId2);
|
|
1559
|
+
if (!exists2) {
|
|
1560
|
+
const tx2 = await this.factory.createAccount(agentId2);
|
|
1561
|
+
await tx2.wait();
|
|
1562
|
+
}
|
|
1563
|
+
const accountAddr2 = await this.factory.getAccount(this.resolvedAgentId);
|
|
1564
|
+
return {
|
|
1565
|
+
tx: "",
|
|
1566
|
+
agentId: this.resolvedAgentId,
|
|
1567
|
+
address: this.signer.address,
|
|
1568
|
+
agentAccount: accountAddr2,
|
|
1569
|
+
alreadyRegistered: true
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
const registrationFile = JSON.stringify({
|
|
1573
|
+
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
|
|
1574
|
+
name,
|
|
1575
|
+
description: "AI agent registered via @agether/sdk",
|
|
1576
|
+
active: true,
|
|
1577
|
+
registrations: [{
|
|
1578
|
+
agentId: 0,
|
|
1579
|
+
agentRegistry: `eip155:8453:${this.config.contracts.agentRegistry}`
|
|
1580
|
+
}]
|
|
1581
|
+
});
|
|
1582
|
+
const agentURI = `data:application/json;base64,${Buffer.from(registrationFile).toString("base64")}`;
|
|
1583
|
+
const tx = await registry["register(string)"](agentURI);
|
|
1584
|
+
const receipt = await tx.wait();
|
|
1585
|
+
const transferTopic = ethers4.id("Transfer(address,address,uint256)");
|
|
1586
|
+
const transferLog = receipt.logs.find((l) => l.topics[0] === transferTopic);
|
|
1587
|
+
if (!transferLog?.topics?.[3]) {
|
|
1588
|
+
throw new Error("Could not parse agentId from receipt");
|
|
1589
|
+
}
|
|
1590
|
+
const agentId = BigInt(transferLog.topics[3]);
|
|
1591
|
+
this.resolvedAgentId = agentId.toString();
|
|
1592
|
+
const exists = await this.factory.accountExists(agentId);
|
|
1593
|
+
if (!exists) {
|
|
1594
|
+
const accTx = await this.factory.createAccount(agentId);
|
|
1595
|
+
await accTx.wait();
|
|
1596
|
+
}
|
|
1597
|
+
const accountAddr = await this.factory.getAccount(this.resolvedAgentId);
|
|
1598
|
+
this.accountAddress = accountAddr;
|
|
1599
|
+
return {
|
|
1600
|
+
tx: tx.hash,
|
|
1601
|
+
agentId: this.resolvedAgentId,
|
|
1602
|
+
address: this.signer.address,
|
|
1603
|
+
agentAccount: accountAddr,
|
|
1604
|
+
alreadyRegistered: false
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
// ══════════════════════════════════════════
|
|
1608
|
+
// Balances & Status
|
|
1609
|
+
// ══════════════════════════════════════════
|
|
1610
|
+
/**
|
|
1611
|
+
* Get ETH and USDC balances for EOA wallet and AgentAccount.
|
|
1612
|
+
*/
|
|
1613
|
+
async getBalances() {
|
|
1614
|
+
const provider = this.signer.provider;
|
|
1615
|
+
const ethBal = await provider.getBalance(this.signer.address);
|
|
1616
|
+
const usdc = new Contract3(this.config.contracts.usdc, ERC20_ABI, provider);
|
|
1617
|
+
const usdcBal = await usdc.balanceOf(this.signer.address);
|
|
1618
|
+
const result = {
|
|
1619
|
+
address: this.signer.address,
|
|
1620
|
+
agentId: this.resolvedAgentId || "not registered",
|
|
1621
|
+
eth: ethers4.formatEther(ethBal),
|
|
1622
|
+
usdc: ethers4.formatUnits(usdcBal, 6)
|
|
1623
|
+
};
|
|
1624
|
+
try {
|
|
1625
|
+
const accountAddr = await this.getAccountAddress();
|
|
1626
|
+
const accEth = await provider.getBalance(accountAddr);
|
|
1627
|
+
const accUsdc = await usdc.balanceOf(accountAddr);
|
|
1628
|
+
result.agentAccount = {
|
|
1629
|
+
address: accountAddr,
|
|
1630
|
+
eth: ethers4.formatEther(accEth),
|
|
1631
|
+
usdc: ethers4.formatUnits(accUsdc, 6)
|
|
1632
|
+
};
|
|
1633
|
+
} catch {
|
|
1634
|
+
}
|
|
1635
|
+
return result;
|
|
1636
|
+
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Get full Morpho credit status — all positions + total debt.
|
|
1639
|
+
*/
|
|
1640
|
+
async getStatus() {
|
|
1641
|
+
const accountAddr = await this.getAccountAddress();
|
|
1642
|
+
const positions = [];
|
|
1643
|
+
for (const [symbol, info] of Object.entries(this.collaterals)) {
|
|
1644
|
+
const pos = await this.morpho.getPosition(accountAddr, info.address);
|
|
1645
|
+
if (pos.isActive || pos.collateralAmount > 0n || pos.borrowedAmount > 0n) {
|
|
1646
|
+
positions.push({
|
|
1647
|
+
token: symbol,
|
|
1648
|
+
collateral: ethers4.formatUnits(pos.collateralAmount, info.decimals),
|
|
1649
|
+
debt: `$${ethers4.formatUnits(pos.borrowedAmount, 6)}`,
|
|
1650
|
+
active: pos.isActive
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1655
|
+
return {
|
|
1656
|
+
agentAccount: accountAddr,
|
|
1657
|
+
totalDebt: `$${ethers4.formatUnits(totalDebt, 6)}`,
|
|
1658
|
+
positions
|
|
1659
|
+
};
|
|
1660
|
+
}
|
|
1661
|
+
// ══════════════════════════════════════════
|
|
1662
|
+
// Fund AgentAccount
|
|
1663
|
+
// ══════════════════════════════════════════
|
|
1664
|
+
/**
|
|
1665
|
+
* Transfer USDC from EOA wallet into AgentAccount.
|
|
1666
|
+
*
|
|
1667
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
1668
|
+
*/
|
|
1669
|
+
async fundAccount(amount) {
|
|
1670
|
+
const amountWei = ethers4.parseUnits(amount, 6);
|
|
1671
|
+
const accountAddr = await this.getAccountAddress();
|
|
1672
|
+
const usdc = new Contract3(this.config.contracts.usdc, ERC20_ABI, this.signer);
|
|
1673
|
+
const balance = await usdc.balanceOf(this.signer.address);
|
|
1674
|
+
if (balance < amountWei) {
|
|
1675
|
+
throw new Error(`Insufficient USDC: have $${ethers4.formatUnits(balance, 6)}, need $${amount}`);
|
|
1676
|
+
}
|
|
1677
|
+
const tx = await usdc.transfer(accountAddr, amountWei);
|
|
1678
|
+
await tx.wait();
|
|
1679
|
+
return { tx: tx.hash, amount, agentAccount: accountAddr };
|
|
1680
|
+
}
|
|
1681
|
+
/**
|
|
1682
|
+
* Check whether a borrow would exceed max LTV.
|
|
1683
|
+
* Call before borrow() or depositAndBorrow() to get a clear error instead of on-chain revert.
|
|
1684
|
+
*
|
|
1685
|
+
* @param tokenSymbol - Collateral token
|
|
1686
|
+
* @param additionalCollateral - Additional collateral being deposited ("0" if just borrowing)
|
|
1687
|
+
* @param borrowAmount - USDC to borrow
|
|
1688
|
+
*/
|
|
1689
|
+
async checkLtv(tokenSymbol, additionalCollateral, borrowAmount) {
|
|
1690
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1691
|
+
const accountAddr = await this.getAccountAddress();
|
|
1692
|
+
const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1693
|
+
const marketInfo = await this.morpho.markets(tokenInfo.address);
|
|
1694
|
+
const oracle = new Contract3(marketInfo.params.oracle, _MorphoCreditClient.ORACLE_ABI, this.signer.provider);
|
|
1695
|
+
const oraclePrice = await oracle.price();
|
|
1696
|
+
const addCollateralWei = ethers4.parseUnits(additionalCollateral, tokenInfo.decimals);
|
|
1697
|
+
const borrowWei = ethers4.parseUnits(borrowAmount, 6);
|
|
1698
|
+
const totalCollateral = pos.collateralAmount + addCollateralWei;
|
|
1699
|
+
const totalDebt = pos.borrowedAmount + borrowWei;
|
|
1700
|
+
const collateralValue = totalCollateral * oraclePrice / BigInt("1000000000000000000000000000000000000");
|
|
1701
|
+
const collateralUsd = Number(collateralValue) / 1e6;
|
|
1702
|
+
const currentDebtUsd = Number(pos.borrowedAmount) / 1e6;
|
|
1703
|
+
const maxLtvBps = Number(marketInfo.maxLtvBps);
|
|
1704
|
+
const currentLtv = collateralValue > 0n ? Number(pos.borrowedAmount * 10000n / collateralValue) / 100 : 0;
|
|
1705
|
+
const newLtv = collateralValue > 0n ? Number(totalDebt * 10000n / collateralValue) / 100 : totalDebt > 0n ? Infinity : 0;
|
|
1706
|
+
const maxLtv = maxLtvBps / 100;
|
|
1707
|
+
const maxBorrow = collateralUsd * maxLtvBps / 1e4;
|
|
1708
|
+
const ok = newLtv <= maxLtv;
|
|
1709
|
+
return {
|
|
1710
|
+
ok,
|
|
1711
|
+
currentLtv,
|
|
1712
|
+
newLtv,
|
|
1713
|
+
maxLtv,
|
|
1714
|
+
collateralUsd,
|
|
1715
|
+
currentDebt: currentDebtUsd,
|
|
1716
|
+
maxBorrow,
|
|
1717
|
+
message: ok ? void 0 : `ExceedsMaxLtv: borrowing $${borrowAmount} would push LTV to ${newLtv.toFixed(1)}% (max ${maxLtv}%). Collateral: $${collateralUsd.toFixed(2)}. Current debt: $${currentDebtUsd.toFixed(3)}. Max additional borrow: $${(maxBorrow - currentDebtUsd).toFixed(2)}. Deposit more collateral or borrow less.`
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
// ══════════════════════════════════════════
|
|
1526
1721
|
// Flow 3: Deposit collateral only
|
|
1527
1722
|
// ══════════════════════════════════════════
|
|
1528
1723
|
/**
|
|
@@ -1563,6 +1758,8 @@ var MorphoCreditClient = class {
|
|
|
1563
1758
|
const collateralWei = ethers4.parseUnits(collateralAmount, tokenInfo.decimals);
|
|
1564
1759
|
const borrowWei = ethers4.parseUnits(borrowAmount, 6);
|
|
1565
1760
|
const accountAddr = await this.getAccountAddress();
|
|
1761
|
+
const ltvCheck = await this.checkLtv(tokenSymbol, collateralAmount, borrowAmount);
|
|
1762
|
+
if (!ltvCheck.ok) throw new Error(ltvCheck.message);
|
|
1566
1763
|
const depositTxHash = await this.approveAndDeposit(accountAddr, tokenInfo, collateralWei);
|
|
1567
1764
|
await this.ensureCreditProvider(accountAddr);
|
|
1568
1765
|
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
@@ -1603,6 +1800,8 @@ var MorphoCreditClient = class {
|
|
|
1603
1800
|
if (!activeToken) {
|
|
1604
1801
|
throw new Error("No collateral deposited. Use deposit() or depositAndBorrow() first.");
|
|
1605
1802
|
}
|
|
1803
|
+
const ltvCheck = await this.checkLtv(activeToken.symbol, "0", amount);
|
|
1804
|
+
if (!ltvCheck.ok) throw new Error(ltvCheck.message);
|
|
1606
1805
|
await this.ensureCreditProvider(accountAddr);
|
|
1607
1806
|
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1608
1807
|
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [activeToken.address, borrowWei]);
|
|
@@ -1808,6 +2007,16 @@ var MorphoCreditClient = class {
|
|
|
1808
2007
|
return this.signer.address;
|
|
1809
2008
|
}
|
|
1810
2009
|
};
|
|
2010
|
+
_MorphoCreditClient.ERC8004_ABI = [
|
|
2011
|
+
"function register(string agentURI) returns (uint256)",
|
|
2012
|
+
"function ownerOf(uint256 tokenId) view returns (address)",
|
|
2013
|
+
"function balanceOf(address owner) view returns (uint256)"
|
|
2014
|
+
];
|
|
2015
|
+
// ══════════════════════════════════════════
|
|
2016
|
+
// LTV Pre-check
|
|
2017
|
+
// ══════════════════════════════════════════
|
|
2018
|
+
_MorphoCreditClient.ORACLE_ABI = ["function price() view returns (uint256)"];
|
|
2019
|
+
var MorphoCreditClient = _MorphoCreditClient;
|
|
1811
2020
|
|
|
1812
2021
|
// src/clients/WalletClient.ts
|
|
1813
2022
|
import { ethers as ethers5, Contract as Contract4, Wallet } from "ethers";
|