@openwallet-foundation/askar-react-native 0.3.0

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.
Files changed (131) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +38 -0
  3. package/android/CMakeLists.txt +60 -0
  4. package/android/build.gradle +261 -0
  5. package/android/cpp-adapter.cpp +36 -0
  6. package/android/src/main/AndroidManifest.xml +3 -0
  7. package/android/src/main/java/foundation/openwallet/askar/AskarModule.java +51 -0
  8. package/android/src/main/java/foundation/openwallet/askar/AskarPackage.java +23 -0
  9. package/android/src/main/java/id/animo/SecureEnvironment.java +5 -0
  10. package/askar.podspec +31 -0
  11. package/build/askar-react-native/src/NativeBindings.d.ts +144 -0
  12. package/build/askar-react-native/src/NativeBindings.js +3 -0
  13. package/build/askar-react-native/src/NativeBindings.js.map +1 -0
  14. package/build/askar-react-native/src/ReactNativeAskar.d.ts +100 -0
  15. package/build/askar-react-native/src/ReactNativeAskar.js +482 -0
  16. package/build/askar-react-native/src/ReactNativeAskar.js.map +1 -0
  17. package/build/askar-react-native/src/index.d.ts +1 -0
  18. package/build/askar-react-native/src/index.js +31 -0
  19. package/build/askar-react-native/src/index.js.map +1 -0
  20. package/build/askar-react-native/src/serialize.d.ts +14 -0
  21. package/build/askar-react-native/src/serialize.js +50 -0
  22. package/build/askar-react-native/src/serialize.js.map +1 -0
  23. package/build/askar-react-native/src/specs/NativeAskar.d.ts +5 -0
  24. package/build/askar-react-native/src/specs/NativeAskar.js +7 -0
  25. package/build/askar-react-native/src/specs/NativeAskar.js.map +1 -0
  26. package/build/askar-shared/src/askar/Askar.d.ts +437 -0
  27. package/build/askar-shared/src/askar/Askar.js +3 -0
  28. package/build/askar-shared/src/askar/Askar.js.map +1 -0
  29. package/build/askar-shared/src/askar/index.d.ts +2 -0
  30. package/build/askar-shared/src/askar/index.js +19 -0
  31. package/build/askar-shared/src/askar/index.js.map +1 -0
  32. package/build/askar-shared/src/askar/register.d.ts +5 -0
  33. package/build/askar-shared/src/askar/register.js +8 -0
  34. package/build/askar-shared/src/askar/register.js.map +1 -0
  35. package/build/askar-shared/src/crypto/AeadParams.d.ts +9 -0
  36. package/build/askar-shared/src/crypto/AeadParams.js +11 -0
  37. package/build/askar-shared/src/crypto/AeadParams.js.map +1 -0
  38. package/build/askar-shared/src/crypto/CryptoBox.d.ts +24 -0
  39. package/build/askar-shared/src/crypto/CryptoBox.js +23 -0
  40. package/build/askar-shared/src/crypto/CryptoBox.js.map +1 -0
  41. package/build/askar-shared/src/crypto/Ecdh1PU.d.ts +58 -0
  42. package/build/askar-shared/src/crypto/Ecdh1PU.js +77 -0
  43. package/build/askar-shared/src/crypto/Ecdh1PU.js.map +1 -0
  44. package/build/askar-shared/src/crypto/EcdhEs.d.ts +46 -0
  45. package/build/askar-shared/src/crypto/EcdhEs.js +64 -0
  46. package/build/askar-shared/src/crypto/EcdhEs.js.map +1 -0
  47. package/build/askar-shared/src/crypto/EncryptedBuffer.d.ts +20 -0
  48. package/build/askar-shared/src/crypto/EncryptedBuffer.js +36 -0
  49. package/build/askar-shared/src/crypto/EncryptedBuffer.js.map +1 -0
  50. package/build/askar-shared/src/crypto/Jwk.d.ts +18 -0
  51. package/build/askar-shared/src/crypto/Jwk.js +24 -0
  52. package/build/askar-shared/src/crypto/Jwk.js.map +1 -0
  53. package/build/askar-shared/src/crypto/Key.d.ts +73 -0
  54. package/build/askar-shared/src/crypto/Key.js +101 -0
  55. package/build/askar-shared/src/crypto/Key.js.map +1 -0
  56. package/build/askar-shared/src/crypto/handles.d.ts +46 -0
  57. package/build/askar-shared/src/crypto/handles.js +123 -0
  58. package/build/askar-shared/src/crypto/handles.js.map +1 -0
  59. package/build/askar-shared/src/crypto/index.d.ts +8 -0
  60. package/build/askar-shared/src/crypto/index.js +25 -0
  61. package/build/askar-shared/src/crypto/index.js.map +1 -0
  62. package/build/askar-shared/src/enums/EntryOperation.d.ts +5 -0
  63. package/build/askar-shared/src/enums/EntryOperation.js +10 -0
  64. package/build/askar-shared/src/enums/EntryOperation.js.map +1 -0
  65. package/build/askar-shared/src/enums/KeyAlgorithm.d.ts +20 -0
  66. package/build/askar-shared/src/enums/KeyAlgorithm.js +38 -0
  67. package/build/askar-shared/src/enums/KeyAlgorithm.js.map +1 -0
  68. package/build/askar-shared/src/enums/KeyBackend.d.ts +6 -0
  69. package/build/askar-shared/src/enums/KeyBackend.js +24 -0
  70. package/build/askar-shared/src/enums/KeyBackend.js.map +1 -0
  71. package/build/askar-shared/src/enums/KeyMethod.d.ts +4 -0
  72. package/build/askar-shared/src/enums/KeyMethod.js +9 -0
  73. package/build/askar-shared/src/enums/KeyMethod.js.map +1 -0
  74. package/build/askar-shared/src/enums/LogLevel.d.ts +9 -0
  75. package/build/askar-shared/src/enums/LogLevel.js +14 -0
  76. package/build/askar-shared/src/enums/LogLevel.js.map +1 -0
  77. package/build/askar-shared/src/enums/SignatureAlgorithm.d.ts +6 -0
  78. package/build/askar-shared/src/enums/SignatureAlgorithm.js +11 -0
  79. package/build/askar-shared/src/enums/SignatureAlgorithm.js.map +1 -0
  80. package/build/askar-shared/src/enums/index.d.ts +5 -0
  81. package/build/askar-shared/src/enums/index.js +22 -0
  82. package/build/askar-shared/src/enums/index.js.map +1 -0
  83. package/build/askar-shared/src/error.d.ts +12 -0
  84. package/build/askar-shared/src/error.js +21 -0
  85. package/build/askar-shared/src/error.js.map +1 -0
  86. package/build/askar-shared/src/index.d.ts +6 -0
  87. package/build/askar-shared/src/index.js +23 -0
  88. package/build/askar-shared/src/index.js.map +1 -0
  89. package/build/askar-shared/src/migration.d.ts +10 -0
  90. package/build/askar-shared/src/migration.js +11 -0
  91. package/build/askar-shared/src/migration.js.map +1 -0
  92. package/build/askar-shared/src/store/Entry.d.ts +21 -0
  93. package/build/askar-shared/src/store/Entry.js +38 -0
  94. package/build/askar-shared/src/store/Entry.js.map +1 -0
  95. package/build/askar-shared/src/store/EntryList.d.ts +17 -0
  96. package/build/askar-shared/src/store/EntryList.js +40 -0
  97. package/build/askar-shared/src/store/EntryList.js.map +1 -0
  98. package/build/askar-shared/src/store/KeyEntry.d.ts +23 -0
  99. package/build/askar-shared/src/store/KeyEntry.js +40 -0
  100. package/build/askar-shared/src/store/KeyEntry.js.map +1 -0
  101. package/build/askar-shared/src/store/KeyEntryList.d.ts +15 -0
  102. package/build/askar-shared/src/store/KeyEntryList.js +33 -0
  103. package/build/askar-shared/src/store/KeyEntryList.js.map +1 -0
  104. package/build/askar-shared/src/store/OpenSession.d.ts +14 -0
  105. package/build/askar-shared/src/store/OpenSession.js +27 -0
  106. package/build/askar-shared/src/store/OpenSession.js.map +1 -0
  107. package/build/askar-shared/src/store/Scan.d.ts +28 -0
  108. package/build/askar-shared/src/store/Scan.js +67 -0
  109. package/build/askar-shared/src/store/Scan.js.map +1 -0
  110. package/build/askar-shared/src/store/Session.d.ts +86 -0
  111. package/build/askar-shared/src/store/Session.js +182 -0
  112. package/build/askar-shared/src/store/Session.js.map +1 -0
  113. package/build/askar-shared/src/store/Store.d.ts +58 -0
  114. package/build/askar-shared/src/store/Store.js +87 -0
  115. package/build/askar-shared/src/store/Store.js.map +1 -0
  116. package/build/askar-shared/src/store/StoreKeyMethod.d.ts +11 -0
  117. package/build/askar-shared/src/store/StoreKeyMethod.js +20 -0
  118. package/build/askar-shared/src/store/StoreKeyMethod.js.map +1 -0
  119. package/build/askar-shared/src/store/index.d.ts +9 -0
  120. package/build/askar-shared/src/store/index.js +26 -0
  121. package/build/askar-shared/src/store/index.js.map +1 -0
  122. package/cpp/HostObject.cpp +198 -0
  123. package/cpp/HostObject.h +23 -0
  124. package/cpp/askar.cpp +1118 -0
  125. package/cpp/askar.h +111 -0
  126. package/cpp/include/libaries_askar.h +635 -0
  127. package/cpp/turboModuleUtility.cpp +598 -0
  128. package/cpp/turboModuleUtility.h +62 -0
  129. package/ios/Askar.h +5 -0
  130. package/ios/Askar.mm +33 -0
  131. package/package.json +59 -0
@@ -0,0 +1,9 @@
1
+ export * from './Entry';
2
+ export * from './EntryList';
3
+ export * from './KeyEntry';
4
+ export * from './KeyEntryList';
5
+ export * from './Scan';
6
+ export * from './Store';
7
+ export * from './OpenSession';
8
+ export * from './Session';
9
+ export * from './StoreKeyMethod';
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Entry"), exports);
18
+ __exportStar(require("./EntryList"), exports);
19
+ __exportStar(require("./KeyEntry"), exports);
20
+ __exportStar(require("./KeyEntryList"), exports);
21
+ __exportStar(require("./Scan"), exports);
22
+ __exportStar(require("./Store"), exports);
23
+ __exportStar(require("./OpenSession"), exports);
24
+ __exportStar(require("./Session"), exports);
25
+ __exportStar(require("./StoreKeyMethod"), exports);
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../askar-shared/src/store/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB;AACvB,8CAA2B;AAC3B,6CAA0B;AAC1B,iDAA8B;AAC9B,yCAAsB;AACtB,0CAAuB;AACvB,gDAA6B;AAC7B,4CAAyB;AACzB,mDAAgC"}
@@ -0,0 +1,198 @@
1
+ #include <algorithm>
2
+ #include <vector>
3
+
4
+ #include "HostObject.h"
5
+
6
+ AskarTurboModuleHostObject::AskarTurboModuleHostObject(
7
+ jsi::Runtime &rt) {
8
+ return;
9
+ }
10
+ FunctionMap AskarTurboModuleHostObject::functionMapping(jsi::Runtime &rt) {
11
+ FunctionMap fMap;
12
+
13
+ fMap.insert(std::make_tuple("version", &askar::version));
14
+ fMap.insert(std::make_tuple("getCurrentError", &askar::getCurrentError));
15
+ fMap.insert(
16
+ std::make_tuple("setDefaultLogger", &askar::setDefaultLogger));
17
+
18
+ fMap.insert(std::make_tuple("storeCopyTo", &askar::storeCopyTo));
19
+ fMap.insert(std::make_tuple("storeOpen", &askar::storeOpen));
20
+ fMap.insert(
21
+ std::make_tuple("storeGenerateRawKey", &askar::storeGenerateRawKey));
22
+ fMap.insert(std::make_tuple("storeProvision", &askar::storeProvision));
23
+ fMap.insert(std::make_tuple("storeOpen", &askar::storeOpen));
24
+ fMap.insert(std::make_tuple("storeClose", &askar::storeClose));
25
+ fMap.insert(
26
+ std::make_tuple("storeCreateProfile", &askar::storeCreateProfile));
27
+ fMap.insert(
28
+ std::make_tuple("storeGenerateRawKey", &askar::storeGenerateRawKey));
29
+ fMap.insert(
30
+ std::make_tuple("storeGetProfileName", &askar::storeGetProfileName));
31
+ fMap.insert(
32
+ std::make_tuple("storeGetDefaultProfile",
33
+ &askar::storeGetDefaultProfile));
34
+ fMap.insert(std::make_tuple("storeProvision", &askar::storeProvision));
35
+ fMap.insert(std::make_tuple("storeRekey", &askar::storeRekey));
36
+ fMap.insert(std::make_tuple("storeRemove", &askar::storeRemove));
37
+ fMap.insert(
38
+ std::make_tuple("storeRemoveProfile", &askar::storeRemoveProfile));
39
+ fMap.insert(
40
+ std::make_tuple("storeSetDefaultProfile",
41
+ &askar::storeSetDefaultProfile));
42
+
43
+ fMap.insert(std::make_tuple("sessionClose", &askar::sessionClose));
44
+ fMap.insert(std::make_tuple("sessionCount", &askar::sessionCount));
45
+ fMap.insert(std::make_tuple("sessionFetch", &askar::sessionFetch));
46
+ fMap.insert(std::make_tuple("sessionFetchAll", &askar::sessionFetchAll));
47
+ fMap.insert(
48
+ std::make_tuple("sessionFetchAllKeys", &askar::sessionFetchAllKeys));
49
+ fMap.insert(std::make_tuple("sessionFetchKey", &askar::sessionFetchKey));
50
+ fMap.insert(
51
+ std::make_tuple("sessionInsertKey", &askar::sessionInsertKey));
52
+ fMap.insert(
53
+ std::make_tuple("sessionRemoveAll", &askar::sessionRemoveAll));
54
+ fMap.insert(
55
+ std::make_tuple("sessionRemoveKey", &askar::sessionRemoveKey));
56
+ fMap.insert(std::make_tuple("sessionStart", &askar::sessionStart));
57
+ fMap.insert(std::make_tuple("sessionUpdate", &askar::sessionUpdate));
58
+ fMap.insert(
59
+ std::make_tuple("sessionUpdateKey", &askar::sessionUpdateKey));
60
+
61
+ fMap.insert(
62
+ std::make_tuple("entryListGetName", &askar::entryListGetName));
63
+ fMap.insert(
64
+ std::make_tuple("entryListGetValue", &askar::entryListGetValue));
65
+ fMap.insert(std::make_tuple("entryListGetCategory",
66
+ &askar::entryListGetCategory));
67
+ fMap.insert(
68
+ std::make_tuple("entryListGetTags", &askar::entryListGetTags));
69
+ fMap.insert(std::make_tuple("entryListCount", &askar::entryListCount));
70
+ fMap.insert(std::make_tuple("entryListFree", &askar::entryListFree));
71
+
72
+ fMap.insert(std::make_tuple("scanFree", &askar::scanFree));
73
+ fMap.insert(std::make_tuple("scanNext", &askar::scanNext));
74
+ fMap.insert(std::make_tuple("scanStart", &askar::scanStart));
75
+
76
+ fMap.insert(std::make_tuple("keyFromJwk", &askar::keyFromJwk));
77
+ fMap.insert(
78
+ std::make_tuple("keyFromKeyExchange", &askar::keyFromKeyExchange));
79
+ fMap.insert(
80
+ std::make_tuple("keyFromPublicBytes", &askar::keyFromPublicBytes));
81
+ fMap.insert(
82
+ std::make_tuple("keyFromSecretBytes", &askar::keyFromSecretBytes));
83
+ fMap.insert(std::make_tuple("keyFromSeed", &askar::keyFromSeed));
84
+ fMap.insert(std::make_tuple("keyGenerate", &askar::keyGenerate));
85
+ fMap.insert(std::make_tuple("keyGetAlgorithm", &askar::keyGetAlgorithm));
86
+ fMap.insert(std::make_tuple("keyGetEphemeral", &askar::keyGetEphemeral));
87
+ fMap.insert(std::make_tuple("keyGetJwkPublic", &askar::keyGetJwkPublic));
88
+ fMap.insert(std::make_tuple("keyGetJwkSecret", &askar::keyGetJwkSecret));
89
+ fMap.insert(
90
+ std::make_tuple("keyGetJwkThumbprint", &askar::keyGetJwkThumbprint));
91
+ fMap.insert(
92
+ std::make_tuple("keyGetPublicBytes", &askar::keyGetPublicBytes));
93
+ fMap.insert(
94
+ std::make_tuple("keyGetSecretBytes", &askar::keyGetSecretBytes));
95
+ fMap.insert(std::make_tuple("keySignMessage", &askar::keySignMessage));
96
+ fMap.insert(std::make_tuple("keyUnwrapKey", &askar::keyUnwrapKey));
97
+ fMap.insert(
98
+ std::make_tuple("keyVerifySignature", &askar::keyVerifySignature));
99
+ fMap.insert(std::make_tuple("keyWrapKey", &askar::keyWrapKey));
100
+
101
+ fMap.insert(std::make_tuple("keyConvert", &askar::keyConvert));
102
+ fMap.insert(std::make_tuple("keyFree", &askar::keyFree));
103
+
104
+ fMap.insert(std::make_tuple("keyCryptoBox", &askar::keyCryptoBox));
105
+ fMap.insert(
106
+ std::make_tuple("keyCryptoBoxOpen", &askar::keyCryptoBoxOpen));
107
+ fMap.insert(std::make_tuple("keyCryptoBoxRandomNonce",
108
+ &askar::keyCryptoBoxRandomNonce));
109
+ fMap.insert(
110
+ std::make_tuple("keyCryptoBoxSeal", &askar::keyCryptoBoxSeal));
111
+ fMap.insert(std::make_tuple("keyCryptoBoxSealOpen",
112
+ &askar::keyCryptoBoxSealOpen));
113
+
114
+ fMap.insert(
115
+ std::make_tuple("keyDeriveEcdh1pu", &askar::keyDeriveEcdh1pu));
116
+ fMap.insert(std::make_tuple("keyDeriveEcdhEs", &askar::keyDeriveEcdhEs));
117
+
118
+ fMap.insert(std::make_tuple("keyAeadDecrypt", &askar::keyAeadDecrypt));
119
+ fMap.insert(std::make_tuple("keyAeadEncrypt", &askar::keyAeadEncrypt));
120
+ fMap.insert(
121
+ std::make_tuple("keyAeadGetPadding", &askar::keyAeadGetPadding));
122
+ fMap.insert(
123
+ std::make_tuple("keyAeadGetParams", &askar::keyAeadGetParams));
124
+ fMap.insert(
125
+ std::make_tuple("keyAeadRandomNonce", &askar::keyAeadRandomNonce));
126
+
127
+ fMap.insert(
128
+ std::make_tuple("keyEntryListCount", &askar::keyEntryListCount));
129
+ fMap.insert(
130
+ std::make_tuple("keyEntryListFree", &askar::keyEntryListFree));
131
+ fMap.insert(std::make_tuple("keyEntryListGetAlgorithm",
132
+ &askar::keyEntryListGetAlgorithm));
133
+ fMap.insert(std::make_tuple("keyEntryListGetMetadata",
134
+ &askar::keyEntryListGetMetadata));
135
+ fMap.insert(
136
+ std::make_tuple("keyEntryListGetName", &askar::keyEntryListGetName));
137
+ fMap.insert(
138
+ std::make_tuple("keyEntryListGetTags", &askar::keyEntryListGetTags));
139
+ fMap.insert(std::make_tuple("keyEntryListLoadLocal",
140
+ &askar::keyEntryListLoadLocal));
141
+
142
+ fMap.insert(std::make_tuple("migrateIndySdk", &askar::migrateIndySdk));
143
+
144
+ return fMap;
145
+ }
146
+
147
+ jsi::Function AskarTurboModuleHostObject::call(jsi::Runtime &rt,
148
+ const char *name, Cb cb) {
149
+ return jsi::Function::createFromHostFunction(
150
+ rt, jsi::PropNameID::forAscii(rt, name), 1,
151
+ [this, cb](jsi::Runtime &rt, const jsi::Value &thisValue,
152
+ const jsi::Value *arguments, size_t count) -> jsi::Value {
153
+ const jsi::Value *val = &arguments[0];
154
+ askarTurboModuleUtility::assertValueIsObject(rt, val);
155
+ return (*cb)(rt, val->getObject(rt));
156
+ });
157
+ };
158
+
159
+ std::vector<jsi::PropNameID>
160
+ AskarTurboModuleHostObject::getPropertyNames(jsi::Runtime &rt) {
161
+ auto fMap = AskarTurboModuleHostObject::functionMapping(rt);
162
+ std::vector<jsi::PropNameID> result;
163
+ for (FunctionMap::iterator it = fMap.begin(); it != fMap.end(); ++it) {
164
+ result.push_back(jsi::PropNameID::forUtf8(rt, it->first));
165
+ }
166
+
167
+ return result;
168
+ }
169
+
170
+ jsi::Value
171
+ AskarTurboModuleHostObject::get(jsi::Runtime &rt,
172
+ const jsi::PropNameID &propNameId) {
173
+ auto propName = propNameId.utf8(rt);
174
+ auto fMap = AskarTurboModuleHostObject::functionMapping(rt);
175
+ for (FunctionMap::iterator it = fMap.begin(); it != fMap.end(); ++it) {
176
+ if (it->first == propName) {
177
+ return AskarTurboModuleHostObject::call(rt, it->first, it->second);
178
+ }
179
+ }
180
+
181
+ /*
182
+ * https://overreacted.io/why-do-react-elements-have-typeof-property/
183
+ *
184
+ * This is a special React key on the object that `React.createElement()`
185
+ * returns.
186
+ *
187
+ * This function is called under-the-hood to see if this React element is
188
+ * renderable.
189
+ *
190
+ * When we return undefined, instead of `Symbol.for('react.element'), we tell
191
+ * React that this element is not renderable.
192
+ *
193
+ */
194
+ if (propName == "$$typeof")
195
+ return jsi::Value::undefined();
196
+
197
+ throw jsi::JSError(rt, "Function: " + propName + " is not defined");
198
+ }
@@ -0,0 +1,23 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <map>
5
+
6
+ #include "turboModuleUtility.h"
7
+ #include "askar.h"
8
+
9
+ using namespace facebook;
10
+
11
+ typedef jsi::Value (*Cb)(jsi::Runtime &rt, jsi::Object options);
12
+ typedef std::map<const char *, Cb> FunctionMap;
13
+
14
+ class JSI_EXPORT AskarTurboModuleHostObject : public jsi::HostObject {
15
+ public:
16
+ AskarTurboModuleHostObject(jsi::Runtime &rt);
17
+ jsi::Function call(jsi::Runtime &rt, const char *name, Cb cb);
18
+ FunctionMap functionMapping(jsi::Runtime &rt);
19
+
20
+ public:
21
+ jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name) override;
22
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
23
+ };