@primuslabs/fund-js-sdk 0.1.2 → 0.1.4

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 CHANGED
@@ -43,7 +43,9 @@ type RecipientBaseInfo = {
43
43
  socialPlatform: string;// The name of the social platform.
44
44
  userIdentifier: string;// The user’s unique identifier on the platforms.
45
45
  }
46
-
46
+ type RefundParam = RecipientBaseInfo &{
47
+ tipTimestamp?: number; // unit: s
48
+ }
47
49
  type RecipientInfo = RecipientBaseInfo & {
48
50
  tokenAmount: string;// The amount of the token
49
51
  nftIds?: bigint[] | [];// The nft token ids when token is nft.
@@ -65,4 +67,4 @@ type AttestParams = {
65
67
  address: string
66
68
  }
67
69
 
68
- export type { AttNetworkRequest, AttNetworkResponseResolve, AttestParams, Attestation, Attestor, ClaimParam, FundParam, RecipientBaseInfo, RecipientInfo, TokenInfo, TokenType };
70
+ export type { AttNetworkRequest, AttNetworkResponseResolve, AttestParams, Attestation, Attestor, ClaimParam, FundParam, RecipientBaseInfo, RecipientInfo, RefundParam, TokenInfo, TokenType };
package/dist/index.d.ts CHANGED
@@ -43,7 +43,9 @@ type RecipientBaseInfo = {
43
43
  socialPlatform: string;// The name of the social platform.
44
44
  userIdentifier: string;// The user’s unique identifier on the platforms.
45
45
  }
46
-
46
+ type RefundParam = RecipientBaseInfo &{
47
+ tipTimestamp?: number; // unit: s
48
+ }
47
49
  type RecipientInfo = RecipientBaseInfo & {
48
50
  tokenAmount: string;// The amount of the token
49
51
  nftIds?: bigint[] | [];// The nft token ids when token is nft.
@@ -65,4 +67,4 @@ type AttestParams = {
65
67
  address: string
66
68
  }
67
69
 
68
- export type { AttNetworkRequest, AttNetworkResponseResolve, AttestParams, Attestation, Attestor, ClaimParam, FundParam, RecipientBaseInfo, RecipientInfo, TokenInfo, TokenType };
70
+ export type { AttNetworkRequest, AttNetworkResponseResolve, AttestParams, Attestation, Attestor, ClaimParam, FundParam, RecipientBaseInfo, RecipientInfo, RefundParam, TokenInfo, TokenType };
package/dist/index.js CHANGED
@@ -94,8 +94,14 @@ var Contract = class {
94
94
  }
95
95
  this.address = address;
96
96
  this.provider = provider;
97
- const signer = this.provider.getSigner();
98
- this.contractInstance = new import_ethers.ethers.Contract(this.address, abiJson, signer);
97
+ let formatProvider;
98
+ if (provider instanceof import_ethers.ethers.providers.JsonRpcProvider) {
99
+ formatProvider = provider;
100
+ } else {
101
+ const web3Provider = new import_ethers.ethers.providers.Web3Provider(provider);
102
+ formatProvider = web3Provider.getSigner();
103
+ }
104
+ this.contractInstance = new import_ethers.ethers.Contract(this.address, abiJson, formatProvider);
99
105
  }
100
106
  // Example method to read from the contract
101
107
  async callMethod(functionName, functionParams) {
@@ -118,22 +124,26 @@ var Contract = class {
118
124
  return reject(`Method ${functionName} does not exist on the contract`);
119
125
  }
120
126
  try {
121
- console.log("sendTransaction params:", ...functionParams);
127
+ console.log("sendTransaction params:", functionName, ...functionParams);
122
128
  const tx = await this.contractInstance[functionName](...functionParams);
123
129
  const txreceipt = await tx.wait();
124
130
  console.log("txreceipt", txreceipt);
125
131
  resolve(txreceipt);
126
132
  } catch (error) {
127
133
  console.log("sendTransaction error:", error);
128
- const errStr = error?.toString()?.toLowerCase() || "";
129
- if (error?.code === "ACTION_REJECTED" || errStr.indexOf("user rejected") > -1 || errStr.indexOf("approval denied") > -1) {
134
+ const errStr = error?.message || error?.toString()?.toLowerCase() || "";
135
+ const userRejectErrStrArr = ["user rejected", "approval denied"];
136
+ const isUserRejected = userRejectErrStrArr.some((str) => errStr.indexOf(str) > -1);
137
+ if (error?.code === "ACTION_REJECTED" || isUserRejected) {
130
138
  return reject("user rejected transaction");
131
139
  }
132
- if (error?.reason) {
133
- return reject(error.reason);
140
+ const insufficientBalanceErrStrArr = ["insufficient balance", "unpredictable_gas_limit"];
141
+ const isInsufficientBalance = insufficientBalanceErrStrArr.some((str) => errStr.indexOf(str) > -1);
142
+ if (isInsufficientBalance) {
143
+ return reject("insufficient balance");
134
144
  }
135
- if (error?.data?.message === "insufficient balance") {
136
- return reject(error?.data?.message);
145
+ if (errStr.indexOf("no pending withdrawals") > -1) {
146
+ return reject("no pending withdrawals");
137
147
  }
138
148
  return reject(error);
139
149
  }
@@ -592,10 +602,11 @@ var abi_default = [
592
602
  {
593
603
  name: "tipRecipients",
594
604
  type: "tuple[]",
595
- internalType: "struct TipRecipient[]",
605
+ internalType: "struct TipWithdrawInfo[]",
596
606
  components: [
597
607
  { name: "idSource", type: "string", internalType: "string" },
598
- { name: "id", type: "string", internalType: "string" }
608
+ { name: "id", type: "string", internalType: "string" },
609
+ { name: "tipTimestamp", type: "uint64", internalType: "uint64" }
599
610
  ]
600
611
  }
601
612
  ],
@@ -628,6 +639,12 @@ var abi_default = [
628
639
  indexed: true,
629
640
  internalType: "address"
630
641
  },
642
+ {
643
+ name: "claimTime",
644
+ type: "uint64",
645
+ indexed: false,
646
+ internalType: "uint64"
647
+ },
631
648
  {
632
649
  name: "idSource",
633
650
  type: "string",
@@ -657,6 +674,12 @@ var abi_default = [
657
674
  type: "uint256",
658
675
  indexed: false,
659
676
  internalType: "uint256"
677
+ },
678
+ {
679
+ name: "tipTime",
680
+ type: "uint64",
681
+ indexed: false,
682
+ internalType: "uint64"
660
683
  }
661
684
  ],
662
685
  anonymous: false
@@ -714,6 +737,24 @@ var abi_default = [
714
737
  type: "address",
715
738
  indexed: false,
716
739
  internalType: "address"
740
+ },
741
+ {
742
+ name: "tokenAddr",
743
+ type: "address",
744
+ indexed: false,
745
+ internalType: "address"
746
+ },
747
+ {
748
+ name: "amount",
749
+ type: "uint256",
750
+ indexed: false,
751
+ internalType: "uint256"
752
+ },
753
+ {
754
+ name: "tipTime",
755
+ type: "uint64",
756
+ indexed: false,
757
+ internalType: "uint64"
717
758
  }
718
759
  ],
719
760
  anonymous: false
@@ -722,16 +763,34 @@ var abi_default = [
722
763
  type: "event",
723
764
  name: "WithdrawEvent",
724
765
  inputs: [
766
+ {
767
+ name: "withdrawTime",
768
+ type: "uint64",
769
+ indexed: false,
770
+ internalType: "uint64"
771
+ },
772
+ {
773
+ name: "idSource",
774
+ type: "string",
775
+ indexed: false,
776
+ internalType: "string"
777
+ },
778
+ {
779
+ name: "id",
780
+ type: "string",
781
+ indexed: false,
782
+ internalType: "string"
783
+ },
725
784
  {
726
785
  name: "tipper",
727
786
  type: "address",
728
- indexed: true,
787
+ indexed: false,
729
788
  internalType: "address"
730
789
  },
731
790
  {
732
791
  name: "tokenAddr",
733
792
  type: "address",
734
- indexed: true,
793
+ indexed: false,
735
794
  internalType: "address"
736
795
  },
737
796
  {
@@ -739,6 +798,12 @@ var abi_default = [
739
798
  type: "uint256",
740
799
  indexed: false,
741
800
  internalType: "uint256"
801
+ },
802
+ {
803
+ name: "tipTime",
804
+ type: "uint64",
805
+ indexed: false,
806
+ internalType: "uint64"
742
807
  }
743
808
  ],
744
809
  anonymous: false
@@ -1092,7 +1157,13 @@ var Fund = class {
1092
1157
  async init(provider, chainId, appId) {
1093
1158
  return new Promise(async (resolve, reject) => {
1094
1159
  try {
1095
- const network = await provider.getNetwork();
1160
+ let formatProvider;
1161
+ if (provider instanceof import_ethers2.ethers.providers.JsonRpcProvider) {
1162
+ formatProvider = provider;
1163
+ } else {
1164
+ formatProvider = new import_ethers2.ethers.providers.Web3Provider(provider);
1165
+ }
1166
+ const network = await formatProvider.getNetwork();
1096
1167
  const providerChainId = network.chainId;
1097
1168
  console.log("init provider", provider, network);
1098
1169
  if (providerChainId !== chainId) {
@@ -1128,7 +1199,8 @@ var Fund = class {
1128
1199
  let params = [];
1129
1200
  if (tokenInfo.tokenType === 0) {
1130
1201
  await this.approve(tokenInfo, recipientInfos);
1131
- const erc20Contract = new import_ethers2.ethers.Contract(tokenInfo.tokenAddress, erc20Abi_default, this.provider);
1202
+ const web3Provider = new import_ethers2.ethers.providers.Web3Provider(this.provider);
1203
+ const erc20Contract = new import_ethers2.ethers.Contract(tokenInfo.tokenAddress, erc20Abi_default, web3Provider);
1132
1204
  decimals = await erc20Contract.decimals();
1133
1205
  }
1134
1206
  const tokenAmount = parseUnits(recipientInfo.tokenAmount.toString(), decimals);
@@ -1156,7 +1228,8 @@ var Fund = class {
1156
1228
  const newRecipients = recipients.map((i) => {
1157
1229
  return {
1158
1230
  idSource: i.socialPlatform,
1159
- id: i.userIdentifier
1231
+ id: i.userIdentifier,
1232
+ tipTimestamp: i.tipTimestamp
1160
1233
  };
1161
1234
  });
1162
1235
  const result = await this.fundContract.sendTransaction("tipperWithdraw", [newRecipients]);
@@ -1173,7 +1246,8 @@ var Fund = class {
1173
1246
  let params = [];
1174
1247
  if (tokenInfo.tokenType === 0) {
1175
1248
  await this.approve(tokenInfo, recipientInfoList);
1176
- const erc20Contract = new import_ethers2.ethers.Contract(tokenInfo.tokenAddress, erc20Abi_default, this.provider);
1249
+ const web3Provider = new import_ethers2.ethers.providers.Web3Provider(this.provider);
1250
+ const erc20Contract = new import_ethers2.ethers.Contract(tokenInfo.tokenAddress, erc20Abi_default, web3Provider);
1177
1251
  decimals = await erc20Contract.decimals();
1178
1252
  }
1179
1253
  let totalFormatAmount = recipientInfoList.reduce((acc, cur) => acc.add(parseUnits(cur.tokenAmount.toString(), decimals)), import_ethers2.ethers.BigNumber.from(0));
@@ -1201,7 +1275,8 @@ var Fund = class {
1201
1275
  async approve(tokenInfo, recipientInfoList) {
1202
1276
  return new Promise(async (resolve, reject) => {
1203
1277
  try {
1204
- const signer = this.provider.getSigner();
1278
+ const web3Provider = new import_ethers2.ethers.providers.Web3Provider(this.provider);
1279
+ const signer = web3Provider.getSigner();
1205
1280
  const address = await signer.getAddress();
1206
1281
  const erc20Contract = new import_ethers2.ethers.Contract(tokenInfo.tokenAddress, erc20Abi_default, signer);
1207
1282
  const allowance = await erc20Contract.allowance(address, this.fundContract.address);
@@ -1335,7 +1410,8 @@ var Fund = class {
1335
1410
  let decimals = 18;
1336
1411
  let symbol = "";
1337
1412
  if (tokenType === 0) {
1338
- const erc20Contract = new import_ethers2.ethers.Contract(tokenAddress, erc20Abi_default, this.provider);
1413
+ const web3Provider = new import_ethers2.ethers.providers.Web3Provider(this.provider);
1414
+ const erc20Contract = new import_ethers2.ethers.Contract(tokenAddress, erc20Abi_default, web3Provider);
1339
1415
  decimals = await erc20Contract.decimals();
1340
1416
  symbol = await erc20Contract.symbol();
1341
1417
  } else if (tokenType === 1) {
@@ -1379,13 +1455,7 @@ var PrimusFund = class {
1379
1455
  return reject("chainId is not supported");
1380
1456
  }
1381
1457
  this._fund = new Fund();
1382
- let formatProvider;
1383
- if (provider instanceof import_ethers3.ethers.providers.JsonRpcProvider) {
1384
- formatProvider = new import_ethers3.ethers.providers.JsonRpcProvider(defaultRpcUrl);
1385
- } else {
1386
- formatProvider = new import_ethers3.ethers.providers.Web3Provider(provider);
1387
- }
1388
- const result = await this._fund.init(formatProvider, chainId, appId);
1458
+ const result = await this._fund.init(provider, chainId, appId);
1389
1459
  return resolve(result);
1390
1460
  } catch (error) {
1391
1461
  return reject(error);
package/dist/index.mjs CHANGED
@@ -70,8 +70,14 @@ var Contract = class {
70
70
  }
71
71
  this.address = address;
72
72
  this.provider = provider;
73
- const signer = this.provider.getSigner();
74
- this.contractInstance = new ethers.Contract(this.address, abiJson, signer);
73
+ let formatProvider;
74
+ if (provider instanceof ethers.providers.JsonRpcProvider) {
75
+ formatProvider = provider;
76
+ } else {
77
+ const web3Provider = new ethers.providers.Web3Provider(provider);
78
+ formatProvider = web3Provider.getSigner();
79
+ }
80
+ this.contractInstance = new ethers.Contract(this.address, abiJson, formatProvider);
75
81
  }
76
82
  // Example method to read from the contract
77
83
  async callMethod(functionName, functionParams) {
@@ -94,22 +100,26 @@ var Contract = class {
94
100
  return reject(`Method ${functionName} does not exist on the contract`);
95
101
  }
96
102
  try {
97
- console.log("sendTransaction params:", ...functionParams);
103
+ console.log("sendTransaction params:", functionName, ...functionParams);
98
104
  const tx = await this.contractInstance[functionName](...functionParams);
99
105
  const txreceipt = await tx.wait();
100
106
  console.log("txreceipt", txreceipt);
101
107
  resolve(txreceipt);
102
108
  } catch (error) {
103
109
  console.log("sendTransaction error:", error);
104
- const errStr = error?.toString()?.toLowerCase() || "";
105
- if (error?.code === "ACTION_REJECTED" || errStr.indexOf("user rejected") > -1 || errStr.indexOf("approval denied") > -1) {
110
+ const errStr = error?.message || error?.toString()?.toLowerCase() || "";
111
+ const userRejectErrStrArr = ["user rejected", "approval denied"];
112
+ const isUserRejected = userRejectErrStrArr.some((str) => errStr.indexOf(str) > -1);
113
+ if (error?.code === "ACTION_REJECTED" || isUserRejected) {
106
114
  return reject("user rejected transaction");
107
115
  }
108
- if (error?.reason) {
109
- return reject(error.reason);
116
+ const insufficientBalanceErrStrArr = ["insufficient balance", "unpredictable_gas_limit"];
117
+ const isInsufficientBalance = insufficientBalanceErrStrArr.some((str) => errStr.indexOf(str) > -1);
118
+ if (isInsufficientBalance) {
119
+ return reject("insufficient balance");
110
120
  }
111
- if (error?.data?.message === "insufficient balance") {
112
- return reject(error?.data?.message);
121
+ if (errStr.indexOf("no pending withdrawals") > -1) {
122
+ return reject("no pending withdrawals");
113
123
  }
114
124
  return reject(error);
115
125
  }
@@ -568,10 +578,11 @@ var abi_default = [
568
578
  {
569
579
  name: "tipRecipients",
570
580
  type: "tuple[]",
571
- internalType: "struct TipRecipient[]",
581
+ internalType: "struct TipWithdrawInfo[]",
572
582
  components: [
573
583
  { name: "idSource", type: "string", internalType: "string" },
574
- { name: "id", type: "string", internalType: "string" }
584
+ { name: "id", type: "string", internalType: "string" },
585
+ { name: "tipTimestamp", type: "uint64", internalType: "uint64" }
575
586
  ]
576
587
  }
577
588
  ],
@@ -604,6 +615,12 @@ var abi_default = [
604
615
  indexed: true,
605
616
  internalType: "address"
606
617
  },
618
+ {
619
+ name: "claimTime",
620
+ type: "uint64",
621
+ indexed: false,
622
+ internalType: "uint64"
623
+ },
607
624
  {
608
625
  name: "idSource",
609
626
  type: "string",
@@ -633,6 +650,12 @@ var abi_default = [
633
650
  type: "uint256",
634
651
  indexed: false,
635
652
  internalType: "uint256"
653
+ },
654
+ {
655
+ name: "tipTime",
656
+ type: "uint64",
657
+ indexed: false,
658
+ internalType: "uint64"
636
659
  }
637
660
  ],
638
661
  anonymous: false
@@ -690,6 +713,24 @@ var abi_default = [
690
713
  type: "address",
691
714
  indexed: false,
692
715
  internalType: "address"
716
+ },
717
+ {
718
+ name: "tokenAddr",
719
+ type: "address",
720
+ indexed: false,
721
+ internalType: "address"
722
+ },
723
+ {
724
+ name: "amount",
725
+ type: "uint256",
726
+ indexed: false,
727
+ internalType: "uint256"
728
+ },
729
+ {
730
+ name: "tipTime",
731
+ type: "uint64",
732
+ indexed: false,
733
+ internalType: "uint64"
693
734
  }
694
735
  ],
695
736
  anonymous: false
@@ -698,16 +739,34 @@ var abi_default = [
698
739
  type: "event",
699
740
  name: "WithdrawEvent",
700
741
  inputs: [
742
+ {
743
+ name: "withdrawTime",
744
+ type: "uint64",
745
+ indexed: false,
746
+ internalType: "uint64"
747
+ },
748
+ {
749
+ name: "idSource",
750
+ type: "string",
751
+ indexed: false,
752
+ internalType: "string"
753
+ },
754
+ {
755
+ name: "id",
756
+ type: "string",
757
+ indexed: false,
758
+ internalType: "string"
759
+ },
701
760
  {
702
761
  name: "tipper",
703
762
  type: "address",
704
- indexed: true,
763
+ indexed: false,
705
764
  internalType: "address"
706
765
  },
707
766
  {
708
767
  name: "tokenAddr",
709
768
  type: "address",
710
- indexed: true,
769
+ indexed: false,
711
770
  internalType: "address"
712
771
  },
713
772
  {
@@ -715,6 +774,12 @@ var abi_default = [
715
774
  type: "uint256",
716
775
  indexed: false,
717
776
  internalType: "uint256"
777
+ },
778
+ {
779
+ name: "tipTime",
780
+ type: "uint64",
781
+ indexed: false,
782
+ internalType: "uint64"
718
783
  }
719
784
  ],
720
785
  anonymous: false
@@ -1068,7 +1133,13 @@ var Fund = class {
1068
1133
  async init(provider, chainId, appId) {
1069
1134
  return new Promise(async (resolve, reject) => {
1070
1135
  try {
1071
- const network = await provider.getNetwork();
1136
+ let formatProvider;
1137
+ if (provider instanceof ethers2.providers.JsonRpcProvider) {
1138
+ formatProvider = provider;
1139
+ } else {
1140
+ formatProvider = new ethers2.providers.Web3Provider(provider);
1141
+ }
1142
+ const network = await formatProvider.getNetwork();
1072
1143
  const providerChainId = network.chainId;
1073
1144
  console.log("init provider", provider, network);
1074
1145
  if (providerChainId !== chainId) {
@@ -1104,7 +1175,8 @@ var Fund = class {
1104
1175
  let params = [];
1105
1176
  if (tokenInfo.tokenType === 0) {
1106
1177
  await this.approve(tokenInfo, recipientInfos);
1107
- const erc20Contract = new ethers2.Contract(tokenInfo.tokenAddress, erc20Abi_default, this.provider);
1178
+ const web3Provider = new ethers2.providers.Web3Provider(this.provider);
1179
+ const erc20Contract = new ethers2.Contract(tokenInfo.tokenAddress, erc20Abi_default, web3Provider);
1108
1180
  decimals = await erc20Contract.decimals();
1109
1181
  }
1110
1182
  const tokenAmount = parseUnits(recipientInfo.tokenAmount.toString(), decimals);
@@ -1132,7 +1204,8 @@ var Fund = class {
1132
1204
  const newRecipients = recipients.map((i) => {
1133
1205
  return {
1134
1206
  idSource: i.socialPlatform,
1135
- id: i.userIdentifier
1207
+ id: i.userIdentifier,
1208
+ tipTimestamp: i.tipTimestamp
1136
1209
  };
1137
1210
  });
1138
1211
  const result = await this.fundContract.sendTransaction("tipperWithdraw", [newRecipients]);
@@ -1149,7 +1222,8 @@ var Fund = class {
1149
1222
  let params = [];
1150
1223
  if (tokenInfo.tokenType === 0) {
1151
1224
  await this.approve(tokenInfo, recipientInfoList);
1152
- const erc20Contract = new ethers2.Contract(tokenInfo.tokenAddress, erc20Abi_default, this.provider);
1225
+ const web3Provider = new ethers2.providers.Web3Provider(this.provider);
1226
+ const erc20Contract = new ethers2.Contract(tokenInfo.tokenAddress, erc20Abi_default, web3Provider);
1153
1227
  decimals = await erc20Contract.decimals();
1154
1228
  }
1155
1229
  let totalFormatAmount = recipientInfoList.reduce((acc, cur) => acc.add(parseUnits(cur.tokenAmount.toString(), decimals)), ethers2.BigNumber.from(0));
@@ -1177,7 +1251,8 @@ var Fund = class {
1177
1251
  async approve(tokenInfo, recipientInfoList) {
1178
1252
  return new Promise(async (resolve, reject) => {
1179
1253
  try {
1180
- const signer = this.provider.getSigner();
1254
+ const web3Provider = new ethers2.providers.Web3Provider(this.provider);
1255
+ const signer = web3Provider.getSigner();
1181
1256
  const address = await signer.getAddress();
1182
1257
  const erc20Contract = new ethers2.Contract(tokenInfo.tokenAddress, erc20Abi_default, signer);
1183
1258
  const allowance = await erc20Contract.allowance(address, this.fundContract.address);
@@ -1311,7 +1386,8 @@ var Fund = class {
1311
1386
  let decimals = 18;
1312
1387
  let symbol = "";
1313
1388
  if (tokenType === 0) {
1314
- const erc20Contract = new ethers2.Contract(tokenAddress, erc20Abi_default, this.provider);
1389
+ const web3Provider = new ethers2.providers.Web3Provider(this.provider);
1390
+ const erc20Contract = new ethers2.Contract(tokenAddress, erc20Abi_default, web3Provider);
1315
1391
  decimals = await erc20Contract.decimals();
1316
1392
  symbol = await erc20Contract.symbol();
1317
1393
  } else if (tokenType === 1) {
@@ -1355,13 +1431,7 @@ var PrimusFund = class {
1355
1431
  return reject("chainId is not supported");
1356
1432
  }
1357
1433
  this._fund = new Fund();
1358
- let formatProvider;
1359
- if (provider instanceof ethers3.providers.JsonRpcProvider) {
1360
- formatProvider = new ethers3.providers.JsonRpcProvider(defaultRpcUrl);
1361
- } else {
1362
- formatProvider = new ethers3.providers.Web3Provider(provider);
1363
- }
1364
- const result = await this._fund.init(formatProvider, chainId, appId);
1434
+ const result = await this._fund.init(provider, chainId, appId);
1365
1435
  return resolve(result);
1366
1436
  } catch (error) {
1367
1437
  return reject(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primuslabs/fund-js-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "author": "Primus Labs <dev@primuslabs.org>",
5
5
  "description": "Primus fund js sdk",
6
6
  "repository": {